From 5ea63d95af08312a65687e2fec10c6d5416f8241 Mon Sep 17 00:00:00 2001 From: stslex Date: Sat, 14 Dec 2024 17:59:40 +0300 Subject: [PATCH] refactor handlers to match option --- .../core/ui/mvi/store_di/StoreBeanV2.kt | 12 +++---- .../stslex/wizard/core/ui/mvi/v2/BaseStore.kt | 9 +++--- .../wizard/core/ui/mvi/v2/BaseStoreImpl.kt | 8 ++--- .../stslex/wizard/core/ui/mvi/v2/Handler.kt | 9 ++---- .../wizard/core/ui/mvi/v2/HandlerCreator.kt | 10 ++++++ .../stslex/wizard/core/ui/mvi/v2/StoreExt.kt | 21 +++++-------- .../profile/di/ModuleFeatureProfile.kt | 12 +++++++ .../feature/profile/mvi/ClickersHandler.kt | 22 ++++++------- .../feature/profile/mvi/InitStorageHandler.kt | 9 ++---- .../feature/profile/mvi/LogoutHandler.kt | 7 ++--- .../feature/profile/mvi/NavigationHandler.kt | 9 ++---- .../profile/mvi/RepeatLastActionHandler.kt | 10 ++---- .../profile/ui/store/ProfileHandlerStore.kt | 8 +++++ .../profile/ui/store/ProfileStoreImpl.kt | 31 ++++++++++--------- 14 files changed, 93 insertions(+), 84 deletions(-) create mode 100644 core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/HandlerCreator.kt create mode 100644 feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/ui/store/ProfileHandlerStore.kt diff --git a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/store_di/StoreBeanV2.kt b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/store_di/StoreBeanV2.kt index b082850..cce83b0 100644 --- a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/store_di/StoreBeanV2.kt +++ b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/store_di/StoreBeanV2.kt @@ -5,32 +5,32 @@ import org.koin.core.definition.BeanDefinition import org.koin.core.definition.KoinDefinition import org.koin.core.module.Module -inline fun > Module.storeOf( +inline fun > Module.storeOf( crossinline constructor: () -> R, noinline options: (BeanDefinition.() -> Unit)? = null, ): KoinDefinition = viewModelOf(constructor, options) -inline fun , reified T1> Module.storeOf( +inline fun , reified T1> Module.storeOf( crossinline constructor: (T1) -> R, noinline options: (BeanDefinition.() -> Unit)? = null, ): KoinDefinition = viewModelOf(constructor, options) -inline fun , reified T1, reified T2> Module.storeOf( +inline fun , reified T1, reified T2> Module.storeOf( crossinline constructor: (T1, T2) -> R, noinline options: (BeanDefinition.() -> Unit)? = null, ): KoinDefinition = viewModelOf(constructor, options) -inline fun , reified T1, reified T2, reified T3> Module.storeOf( +inline fun , reified T1, reified T2, reified T3> Module.storeOf( crossinline constructor: (T1, T2, T3) -> R, noinline options: (BeanDefinition.() -> Unit)? = null, ): KoinDefinition = viewModelOf(constructor, options) -inline fun , reified T1, reified T2, reified T3, reified T4> Module.storeOf( +inline fun , reified T1, reified T2, reified T3, reified T4> Module.storeOf( crossinline constructor: (T1, T2, T3, T4) -> R, noinline options: (BeanDefinition.() -> Unit)? = null, ): KoinDefinition = viewModelOf(constructor, options) -inline fun , reified T1, reified T2, reified T3, reified T4, reified T5> Module.storeOf( +inline fun , reified T1, reified T2, reified T3, reified T4, reified T5> Module.storeOf( crossinline constructor: (T1, T2, T3, T4, T5) -> R, noinline options: (BeanDefinition.() -> Unit)? = null, ): KoinDefinition = viewModelOf(constructor, options) \ No newline at end of file diff --git a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/BaseStore.kt b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/BaseStore.kt index a36f35a..e38deec 100644 --- a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/BaseStore.kt +++ b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/BaseStore.kt @@ -22,9 +22,9 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -open class BaseStore( +open class BaseStore>( initialState: S, - private val handlers: Set> + private val handlerCreator: HandlerCreator, ) : ViewModel(), Store, HandlerStore { private val _event: MutableSharedFlow = MutableSharedFlow() @@ -44,9 +44,8 @@ open class BaseStore( if (lastAction != action && action !is Action.RepeatLast) { _lastAction = action } - val handler = handlers.firstOrNull { it.checkAction(action) } as? Handler - ?: throw IllegalStateException("Handler not found for action: ${action::class.simpleName}") - handler.invoke(this, action) + val handler = handlerCreator(action) as Handler + handler.invoke(this as HStore, action) } /** diff --git a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/BaseStoreImpl.kt b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/BaseStoreImpl.kt index 6d175c6..374cdb1 100644 --- a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/BaseStoreImpl.kt +++ b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/BaseStoreImpl.kt @@ -4,10 +4,10 @@ import com.stslex.wizard.core.ui.mvi.Store.Action import com.stslex.wizard.core.ui.mvi.Store.Event import com.stslex.wizard.core.ui.mvi.Store.State -internal class BaseStoreImpl( +internal class BaseStoreImpl>( initialState: S, - handlers: Set> -) : BaseStore( + handlerCreator: HandlerCreator, +) : BaseStore( initialState = initialState, - handlers = handlers + handlerCreator = handlerCreator ) \ No newline at end of file diff --git a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/Handler.kt b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/Handler.kt index 06c2eb9..54eadda 100644 --- a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/Handler.kt +++ b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/Handler.kt @@ -1,14 +1,9 @@ package com.stslex.wizard.core.ui.mvi.v2 import com.stslex.wizard.core.ui.mvi.Store.Action -import com.stslex.wizard.core.ui.mvi.Store.Event -import com.stslex.wizard.core.ui.mvi.Store.State -import kotlin.reflect.KClass -abstract class Handler(val actionKClass: KClass<*>) { +fun interface Handler> { - inline fun checkAction(action: StoreAction): Boolean = actionKClass.isInstance(action) - - abstract fun HandlerStore.invoke(action: A) + fun TStore.invoke(action: A) } diff --git a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/HandlerCreator.kt b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/HandlerCreator.kt new file mode 100644 index 0000000..41979d0 --- /dev/null +++ b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/HandlerCreator.kt @@ -0,0 +1,10 @@ +package com.stslex.wizard.core.ui.mvi.v2 + +import com.stslex.wizard.core.ui.mvi.Store.Action +import com.stslex.wizard.core.ui.mvi.Store.Event +import com.stslex.wizard.core.ui.mvi.Store.State + +fun interface HandlerCreator> { + + operator fun invoke(action: A): Handler<*, HStore> +} \ No newline at end of file diff --git a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/StoreExt.kt b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/StoreExt.kt index c6040c4..0a939c1 100644 --- a/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/StoreExt.kt +++ b/core/ui/mvi/src/commonMain/kotlin/com/stslex/wizard/core/ui/mvi/v2/StoreExt.kt @@ -6,13 +6,13 @@ import com.stslex.wizard.core.ui.mvi.Store.Event import com.stslex.wizard.core.ui.mvi.Store.State @Suppress("UNCHECKED_CAST") -fun > store( +fun , HStore : HandlerStore> store( initialState: S, - handlers: Set> -): TStore = BaseStoreImpl(initialState, handlers) as TStore + handlerCreator: HandlerCreator +): TStore = BaseStoreImpl(initialState, handlerCreator) as TStore -fun Handler.invoke( - store: HandlerStore, +fun > Handler.invoke( + store: HStore, action: A ) { with(store) { @@ -20,11 +20,6 @@ fun Handler handler( - crossinline block: HandlerStore.(action: A) -> Unit -) = object : Handler(A::class) { - - override fun HandlerStore.invoke(action: A) { - block(action) - } -} +inline fun > handler( + crossinline block: HandlerStore.(action: A) -> Unit +) = Handler { block(it) } diff --git a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/di/ModuleFeatureProfile.kt b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/di/ModuleFeatureProfile.kt index 78fc82e..e2ac331 100644 --- a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/di/ModuleFeatureProfile.kt +++ b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/di/ModuleFeatureProfile.kt @@ -6,6 +6,11 @@ import com.stslex.wizard.feature.profile.data.repository.ProfileRepository import com.stslex.wizard.feature.profile.data.repository.ProfileRepositoryImpl import com.stslex.wizard.feature.profile.domain.interactor.ProfileInteractor import com.stslex.wizard.feature.profile.domain.interactor.ProfileInteractorImpl +import com.stslex.wizard.feature.profile.mvi.ClickersHandler +import com.stslex.wizard.feature.profile.mvi.InitStorageHandler +import com.stslex.wizard.feature.profile.mvi.LogoutHandler +import com.stslex.wizard.feature.profile.mvi.NavigationHandler +import com.stslex.wizard.feature.profile.mvi.RepeatLastActionHandler import com.stslex.wizard.feature.profile.ui.store.ProfileStore import com.stslex.wizard.feature.profile.ui.store.ProfileStoreImpl import org.koin.core.annotation.Module @@ -17,7 +22,14 @@ import org.koin.dsl.ModuleDeclaration class ModuleFeatureProfile : AppModule() { override fun declaration(): ModuleDeclaration = { + factoryOf(::InitStorageHandler) + factoryOf(::LogoutHandler) + factoryOf(::RepeatLastActionHandler) + factoryOf(::ClickersHandler) + factoryOf(::NavigationHandler) + storeOf(::ProfileStoreImpl) { bind() } + factoryOf(::ProfileInteractorImpl) { bind() } factoryOf(::ProfileRepositoryImpl) { bind() } } diff --git a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/ClickersHandler.kt b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/ClickersHandler.kt index bbc76dd..72b8906 100644 --- a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/ClickersHandler.kt +++ b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/ClickersHandler.kt @@ -1,18 +1,18 @@ package com.stslex.wizard.feature.profile.mvi import com.stslex.wizard.core.ui.mvi.v2.Handler -import com.stslex.wizard.core.ui.mvi.v2.handler +import com.stslex.wizard.feature.profile.ui.store.ProfileHandlerStore import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action.Click -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Event -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.State -fun clickersHandler(): Handler = handler { action -> - when (action) { - Click.BackButtonClick -> sendAction(Action.Navigation.Back) - Click.FavouriteClick -> sendAction(Action.Navigation.Favourite(state.value.uuid)) - Click.FollowersClick -> sendAction(Action.Navigation.Followers(state.value.uuid)) - Click.FollowingClick -> sendAction(Action.Navigation.Following(state.value.uuid)) - Click.SettingsClick -> sendAction(Action.Navigation.Settings) +class ClickersHandler : Handler { + + override fun ProfileHandlerStore.invoke(action: Action.Click) { + when (action) { + Action.Click.BackButtonClick -> sendAction(Action.Navigation.Back) + Action.Click.FavouriteClick -> sendAction(Action.Navigation.Favourite(state.value.uuid)) + Action.Click.FollowersClick -> sendAction(Action.Navigation.Followers(state.value.uuid)) + Action.Click.FollowingClick -> sendAction(Action.Navigation.Following(state.value.uuid)) + Action.Click.SettingsClick -> sendAction(Action.Navigation.Settings) + } } } diff --git a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/InitStorageHandler.kt b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/InitStorageHandler.kt index 7a70763..c61fcd2 100644 --- a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/InitStorageHandler.kt +++ b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/InitStorageHandler.kt @@ -4,22 +4,19 @@ import androidx.compose.ui.graphics.Color import com.stslex.wizard.core.database.store.UserStore import com.stslex.wizard.core.navigation.Screen import com.stslex.wizard.core.ui.mvi.v2.Handler -import com.stslex.wizard.core.ui.mvi.v2.HandlerStore import com.stslex.wizard.feature.profile.domain.interactor.ProfileInteractor import com.stslex.wizard.feature.profile.ui.model.ProfileAvatarModel import com.stslex.wizard.feature.profile.ui.model.toUi +import com.stslex.wizard.feature.profile.ui.store.ProfileHandlerStore import com.stslex.wizard.feature.profile.ui.store.ProfileScreenState import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action.Init -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Event -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.State class InitStorageHandler( private val interactor: ProfileInteractor, private val userStore: UserStore, -) : Handler(Init::class) { +) : Handler { - override fun HandlerStore.invoke(action: Init) { + override fun ProfileHandlerStore.invoke(action: Action.Init) { val uuid = action.uuid.ifBlank { userStore.uuid } updateState { currentState -> diff --git a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/LogoutHandler.kt b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/LogoutHandler.kt index 3a6d81e..9e3bd54 100644 --- a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/LogoutHandler.kt +++ b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/LogoutHandler.kt @@ -2,18 +2,17 @@ package com.stslex.wizard.feature.profile.mvi import com.stslex.wizard.core.ui.mvi.CommonEvents.Snackbar import com.stslex.wizard.core.ui.mvi.v2.Handler -import com.stslex.wizard.core.ui.mvi.v2.HandlerStore import com.stslex.wizard.feature.profile.domain.interactor.ProfileInteractor +import com.stslex.wizard.feature.profile.ui.store.ProfileHandlerStore import com.stslex.wizard.feature.profile.ui.store.ProfileScreenState import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Event -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.State class LogoutHandler( private val interactor: ProfileInteractor, -) : Handler(Action.Logout::class) { +) : Handler { - override fun HandlerStore.invoke(action: Action.Logout) { + override fun ProfileHandlerStore.invoke(action: Action.Logout) { val currentScreen = state.value.screen if ( diff --git a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/NavigationHandler.kt b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/NavigationHandler.kt index 231be6c..47bec5e 100644 --- a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/NavigationHandler.kt +++ b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/NavigationHandler.kt @@ -5,17 +5,14 @@ import com.stslex.wizard.core.navigation.Screen.Follower.FollowerType.FOLLOWER import com.stslex.wizard.core.navigation.Screen.Follower.FollowerType.FOLLOWING import com.stslex.wizard.core.navigation.navigator.Navigator import com.stslex.wizard.core.ui.mvi.v2.Handler -import com.stslex.wizard.core.ui.mvi.v2.HandlerStore -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action +import com.stslex.wizard.feature.profile.ui.store.ProfileHandlerStore import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action.Navigation -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Event -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.State class NavigationHandler( private val navigator: Navigator -) : Handler(Navigation::class) { +) : Handler { - override fun HandlerStore.invoke(action: Navigation) { + override fun ProfileHandlerStore.invoke(action: Navigation) { when (action) { Navigation.LogIn -> navigator.navTo(Screen.Auth) Navigation.Back -> navigator.popBack() diff --git a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/RepeatLastActionHandler.kt b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/RepeatLastActionHandler.kt index 54e9dc4..3045e6c 100644 --- a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/RepeatLastActionHandler.kt +++ b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/mvi/RepeatLastActionHandler.kt @@ -2,17 +2,13 @@ package com.stslex.wizard.feature.profile.mvi import com.stslex.wizard.core.ui.mvi.v2.Handler -import com.stslex.wizard.core.ui.mvi.v2.HandlerStore +import com.stslex.wizard.feature.profile.ui.store.ProfileHandlerStore import com.stslex.wizard.feature.profile.ui.store.ProfileScreenState import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action.RepeatLastAction -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Event -import com.stslex.wizard.feature.profile.ui.store.ProfileStore.State -class RepeatLastActionHandler : - Handler(RepeatLastAction::class) { +class RepeatLastActionHandler : Handler { - override fun HandlerStore.invoke(action: RepeatLastAction) { + override fun ProfileHandlerStore.invoke(action: Action.RepeatLastAction) { val lastAction = lastAction ?: return updateState { currentState -> val screen = when (val screen = currentState.screen) { diff --git a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/ui/store/ProfileHandlerStore.kt b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/ui/store/ProfileHandlerStore.kt new file mode 100644 index 0000000..c6e607f --- /dev/null +++ b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/ui/store/ProfileHandlerStore.kt @@ -0,0 +1,8 @@ +package com.stslex.wizard.feature.profile.ui.store + +import com.stslex.wizard.core.ui.mvi.v2.HandlerStore +import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action +import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Event +import com.stslex.wizard.feature.profile.ui.store.ProfileStore.State + +interface ProfileHandlerStore : ProfileStore, HandlerStore \ No newline at end of file diff --git a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/ui/store/ProfileStoreImpl.kt b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/ui/store/ProfileStoreImpl.kt index 193ab4c..c7e5c9e 100644 --- a/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/ui/store/ProfileStoreImpl.kt +++ b/feature/profile/src/commonMain/kotlin/com/stslex/wizard/feature/profile/ui/store/ProfileStoreImpl.kt @@ -1,30 +1,31 @@ package com.stslex.wizard.feature.profile.ui.store -import com.stslex.wizard.core.database.store.UserStore -import com.stslex.wizard.core.navigation.navigator.Navigator import com.stslex.wizard.core.ui.mvi.v2.BaseStore -import com.stslex.wizard.feature.profile.domain.interactor.ProfileInteractor +import com.stslex.wizard.feature.profile.mvi.ClickersHandler import com.stslex.wizard.feature.profile.mvi.InitStorageHandler import com.stslex.wizard.feature.profile.mvi.LogoutHandler import com.stslex.wizard.feature.profile.mvi.NavigationHandler import com.stslex.wizard.feature.profile.mvi.RepeatLastActionHandler -import com.stslex.wizard.feature.profile.mvi.clickersHandler import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Action import com.stslex.wizard.feature.profile.ui.store.ProfileStore.Event import com.stslex.wizard.feature.profile.ui.store.ProfileStore.State class ProfileStoreImpl( - interactor: ProfileInteractor, - userStore: UserStore, - navigator: Navigator -) : ProfileStore, BaseStore( + initStorageHandler: InitStorageHandler, + logoutHandler: LogoutHandler, + repeatLastActionHandler: RepeatLastActionHandler, + clickersHandler: ClickersHandler, + navigationHandler: NavigationHandler +) : ProfileHandlerStore, BaseStore( initialState = State.INITIAL, - handlers = setOf( - InitStorageHandler(interactor, userStore), - LogoutHandler(interactor), - RepeatLastActionHandler(), - clickersHandler(), - NavigationHandler(navigator) - ) + handlerCreator = { action -> + when (action) { + is Action.Init -> initStorageHandler + is Action.Logout -> logoutHandler + is Action.RepeatLastAction -> repeatLastActionHandler + is Action.Click -> clickersHandler + is Action.Navigation -> navigationHandler + } + } )