diff --git a/app/src/main/kotlin/app/dapk/st/SmallTalkApplication.kt b/app/src/main/kotlin/app/dapk/st/SmallTalkApplication.kt index 8a078b7..3310b37 100644 --- a/app/src/main/kotlin/app/dapk/st/SmallTalkApplication.kt +++ b/app/src/main/kotlin/app/dapk/st/SmallTalkApplication.kt @@ -67,7 +67,7 @@ class SmallTalkApplication : Application(), ModuleProvider { } } - @Suppress("UNCHECKED_CAST", "IMPLICIT_CAST_TO_ANY") + @Suppress("UNCHECKED_CAST") override fun provide(klass: KClass): T { return when (klass) { DirectoryModule::class -> featureModules.directoryModule diff --git a/app/src/main/kotlin/app/dapk/st/graph/AppModule.kt b/app/src/main/kotlin/app/dapk/st/graph/AppModule.kt index afe3097..9a059c1 100644 --- a/app/src/main/kotlin/app/dapk/st/graph/AppModule.kt +++ b/app/src/main/kotlin/app/dapk/st/graph/AppModule.kt @@ -190,6 +190,9 @@ internal class FeatureModules internal constructor( storeModule.value.applicationStore(), buildMeta, ), + profileModule, + loginModule, + directoryModule ) } val settingsModule by unsafeLazy { diff --git a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryModule.kt b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryModule.kt index 8ef9027..23318cb 100644 --- a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryModule.kt +++ b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryModule.kt @@ -1,12 +1,13 @@ package app.dapk.st.directory import android.content.Context -import app.dapk.st.core.ProvidableModule -import app.dapk.st.state.createStateViewModel import app.dapk.st.core.JobBag +import app.dapk.st.core.ProvidableModule +import app.dapk.st.directory.state.DirectoryEvent import app.dapk.st.directory.state.DirectoryState import app.dapk.st.directory.state.directoryReducer import app.dapk.st.engine.ChatEngine +import app.dapk.st.state.createStateViewModel class DirectoryModule( private val context: Context, @@ -14,6 +15,8 @@ class DirectoryModule( ) : ProvidableModule { fun directoryState(): DirectoryState { - return createStateViewModel { directoryReducer(chatEngine, ShortcutHandler(context), JobBag(), it) } + return createStateViewModel { directoryReducer(it) } } + + fun directoryReducer(eventEmitter: suspend (DirectoryEvent) -> Unit) = directoryReducer(chatEngine, ShortcutHandler(context), JobBag(), eventEmitter) } diff --git a/features/home/build.gradle b/features/home/build.gradle index fc94fe6..df99340 100644 --- a/features/home/build.gradle +++ b/features/home/build.gradle @@ -13,7 +13,6 @@ dependencies { implementation project(":features:settings") implementation project(":features:profile") implementation project(":domains:android:compose-core") - implementation project(":domains:android:viewmodel") implementation project(':domains:store') implementation 'screen-state:screen-android' implementation project(":core") diff --git a/features/home/src/main/kotlin/app/dapk/st/home/HomeModule.kt b/features/home/src/main/kotlin/app/dapk/st/home/HomeModule.kt index 9cdd68f..9a716cd 100644 --- a/features/home/src/main/kotlin/app/dapk/st/home/HomeModule.kt +++ b/features/home/src/main/kotlin/app/dapk/st/home/HomeModule.kt @@ -1,27 +1,51 @@ package app.dapk.st.home +import app.dapk.st.core.JobBag import app.dapk.st.core.ProvidableModule -import app.dapk.st.directory.state.DirectoryState +import app.dapk.st.directory.DirectoryModule import app.dapk.st.domain.StoreModule import app.dapk.st.engine.ChatEngine -import app.dapk.st.login.state.LoginState -import app.dapk.st.profile.state.ProfileState +import app.dapk.st.home.state.createHomeReducer +import app.dapk.st.login.LoginModule +import app.dapk.st.profile.ProfileModule +import app.dapk.st.state.State +import app.dapk.st.state.createStateViewModel +import app.dapk.state.Action +import app.dapk.state.DynamicReducers +import app.dapk.state.combineReducers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filterIsInstance class HomeModule( private val chatEngine: ChatEngine, private val storeModule: StoreModule, val betaVersionUpgradeUseCase: BetaVersionUpgradeUseCase, + private val profileModule: ProfileModule, + private val loginModule: LoginModule, + private val directoryModule: DirectoryModule, ) : ProvidableModule { - internal fun homeViewModel(directory: DirectoryState, login: LoginState, profile: ProfileState): HomeViewModel { - return HomeViewModel( - chatEngine, - directory, - login, - profile, - storeModule.cacheCleaner(), - betaVersionUpgradeUseCase, - ) + internal fun compositeHomeState(): DynamicState { + return createStateViewModel { + combineReducers( + listOf( + homeReducerFactory(it), + loginModule.loginReducer(it), + profileModule.profileReducer(), + directoryModule.directoryReducer(it) + ) + ) + } } -} \ No newline at end of file + private fun homeReducerFactory(eventEmitter: suspend (Any) -> Unit) = + createHomeReducer(chatEngine, storeModule.cacheCleaner(), betaVersionUpgradeUseCase, JobBag(), eventEmitter) +} + +typealias DynamicState = State + +inline fun DynamicState.childState() = object : State { + override fun dispatch(action: Action) = this@childState.dispatch(action) + override val events: Flow = this@childState.events.filterIsInstance() + override val current: S = this@childState.current.getState() +} diff --git a/features/home/src/main/kotlin/app/dapk/st/home/HomeScreen.kt b/features/home/src/main/kotlin/app/dapk/st/home/HomeScreen.kt index 2cca6ae..22802a1 100644 --- a/features/home/src/main/kotlin/app/dapk/st/home/HomeScreen.kt +++ b/features/home/src/main/kotlin/app/dapk/st/home/HomeScreen.kt @@ -11,9 +11,11 @@ import app.dapk.st.core.components.CenteredLoading import app.dapk.st.design.components.CircleishAvatar import app.dapk.st.directory.DirectoryScreen import app.dapk.st.directory.state.DirectoryState -import app.dapk.st.home.HomeScreenState.* -import app.dapk.st.home.HomeScreenState.Page.Directory -import app.dapk.st.home.HomeScreenState.Page.Profile +import app.dapk.st.home.state.HomeAction +import app.dapk.st.home.state.HomeScreenState.* +import app.dapk.st.home.state.HomeScreenState.Page.Directory +import app.dapk.st.home.state.HomeScreenState.Page.Profile +import app.dapk.st.home.state.HomeState import app.dapk.st.login.LoginScreen import app.dapk.st.login.state.LoginState import app.dapk.st.profile.ProfileScreen @@ -21,18 +23,18 @@ import app.dapk.st.profile.state.ProfileState @OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun HomeScreen(homeViewModel: HomeViewModel, directoryState: DirectoryState, loginState: LoginState, profileState: ProfileState) { +internal fun HomeScreen(homeState: HomeState, directoryState: DirectoryState, loginState: LoginState, profileState: ProfileState) { LifecycleEffect( - onStart = { homeViewModel.start() }, - onStop = { homeViewModel.stop() } + onStart = { homeState.dispatch(HomeAction.LifecycleVisible) }, + onStop = { homeState.dispatch(HomeAction.LifecycleGone) } ) - when (val state = homeViewModel.state) { + when (val state = homeState.current) { Loading -> CenteredLoading() is SignedIn -> { Scaffold( bottomBar = { - BottomBar(state, homeViewModel) + BottomBar(state, homeState) }, content = { innerPadding -> Box(modifier = Modifier.padding(innerPadding)) { @@ -40,7 +42,7 @@ internal fun HomeScreen(homeViewModel: HomeViewModel, directoryState: DirectoryS Directory -> DirectoryScreen(directoryState) Profile -> { ProfileScreen(profileState) { - homeViewModel.changePage(Directory) + homeState.dispatch(HomeAction.ChangePage(Directory)) } } } @@ -51,7 +53,7 @@ internal fun HomeScreen(homeViewModel: HomeViewModel, directoryState: DirectoryS SignedOut -> { LoginScreen(loginState) { - homeViewModel.loggedIn() + homeState.dispatch(HomeAction.LoggedIn) } } } @@ -59,7 +61,7 @@ internal fun HomeScreen(homeViewModel: HomeViewModel, directoryState: DirectoryS @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun BottomBar(state: SignedIn, homeViewModel: HomeViewModel) { +private fun BottomBar(state: SignedIn, homeState: HomeState) { Column { Divider(modifier = Modifier.fillMaxWidth(), color = Color.Black.copy(alpha = 0.2f), thickness = 0.5.dp) NavigationBar(containerColor = Color.Transparent, modifier = Modifier.height(IntrinsicSize.Min)) { @@ -70,8 +72,8 @@ private fun BottomBar(state: SignedIn, homeViewModel: HomeViewModel) { selected = state.page == page, onClick = { when { - state.page == page -> homeViewModel.scrollToTopOfMessages() - else -> homeViewModel.changePage(page) + state.page == page -> homeState.dispatch(HomeAction.ScrollToTop) + else -> homeState.dispatch(HomeAction.ChangePage(page)) } }, ) @@ -89,7 +91,7 @@ private fun BottomBar(state: SignedIn, homeViewModel: HomeViewModel) { } }, selected = state.page == page, - onClick = { homeViewModel.changePage(page) }, + onClick = { homeState.dispatch(HomeAction.ChangePage(page)) }, ) } } diff --git a/features/home/src/main/kotlin/app/dapk/st/home/HomeViewModel.kt b/features/home/src/main/kotlin/app/dapk/st/home/HomeViewModel.kt deleted file mode 100644 index b9cc982..0000000 --- a/features/home/src/main/kotlin/app/dapk/st/home/HomeViewModel.kt +++ /dev/null @@ -1,127 +0,0 @@ -package app.dapk.st.home - -import androidx.lifecycle.viewModelScope -import app.dapk.st.directory.state.ComponentLifecycle -import app.dapk.st.directory.state.DirectorySideEffect -import app.dapk.st.directory.state.DirectoryState -import app.dapk.st.domain.StoreCleaner -import app.dapk.st.engine.ChatEngine -import app.dapk.st.home.HomeScreenState.* -import app.dapk.st.login.state.LoginState -import app.dapk.st.profile.state.ProfileAction -import app.dapk.st.profile.state.ProfileState -import app.dapk.st.viewmodel.DapkViewModel -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch - -internal class HomeViewModel( - private val chatEngine: ChatEngine, - private val directoryState: DirectoryState, - private val loginState: LoginState, - private val profileState: ProfileState, - private val cacheCleaner: StoreCleaner, - private val betaVersionUpgradeUseCase: BetaVersionUpgradeUseCase, -) : DapkViewModel( - initialState = Loading -) { - - private var listenForInvitesJob: Job? = null - - fun start() { - viewModelScope.launch { - state = if (chatEngine.isSignedIn()) { - _events.emit(HomeEvent.OnShowContent) - initialHomeContent() - } else { - SignedOut - } - } - - viewModelScope.launch { - if (chatEngine.isSignedIn()) { - listenForInviteChanges() - } - } - } - - private suspend fun initialHomeContent(): SignedIn { - val me = chatEngine.me(forceRefresh = false) - return when (val current = state) { - Loading -> SignedIn(Page.Directory, me, invites = 0) - is SignedIn -> current.copy(me = me, invites = current.invites) - SignedOut -> SignedIn(Page.Directory, me, invites = 0) - } - } - - fun loggedIn() { - viewModelScope.launch { - state = initialHomeContent() - _events.emit(HomeEvent.OnShowContent) - listenForInviteChanges() - } - } - - private fun CoroutineScope.listenForInviteChanges() { - listenForInvitesJob?.cancel() - listenForInvitesJob = chatEngine.invites() - .onEach { invites -> - when (val currentState = state) { - is SignedIn -> updateState { currentState.copy(invites = invites.size) } - Loading, - SignedOut -> { - // do nothing - } - } - }.launchIn(this) - } - - fun hasVersionChanged() = betaVersionUpgradeUseCase.hasVersionChanged() - - fun clearCache() { - viewModelScope.launch { - cacheCleaner.cleanCache(removeCredentials = false) - betaVersionUpgradeUseCase.notifyUpgraded() - _events.emit(HomeEvent.Relaunch) - } - } - - fun scrollToTopOfMessages() { - directoryState.dispatch(DirectorySideEffect.ScrollToTop) - } - - fun changePage(page: Page) { - state = when (val current = state) { - Loading -> current - is SignedIn -> { - when (page) { - current.page -> current - else -> current.copy(page = page).also { - pageChangeSideEffects(page) - } - } - } - - SignedOut -> current - } - } - - private fun pageChangeSideEffects(page: Page) { - when (page) { - Page.Directory -> { - // do nothing - } - - Page.Profile -> { - directoryState.dispatch(ComponentLifecycle.OnGone) - profileState.dispatch(ProfileAction.Reset) - } - } - } - - fun stop() { - // do nothing - } -} diff --git a/features/home/src/main/kotlin/app/dapk/st/home/MainActivity.kt b/features/home/src/main/kotlin/app/dapk/st/home/MainActivity.kt index a3315b3..268840c 100644 --- a/features/home/src/main/kotlin/app/dapk/st/home/MainActivity.kt +++ b/features/home/src/main/kotlin/app/dapk/st/home/MainActivity.kt @@ -12,26 +12,24 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.lifecycle.lifecycleScope import app.dapk.st.core.DapkActivity +import app.dapk.st.core.extensions.unsafeLazy import app.dapk.st.core.module -import app.dapk.st.core.viewModel -import app.dapk.st.directory.DirectoryModule -import app.dapk.st.login.LoginModule -import app.dapk.st.profile.ProfileModule +import app.dapk.st.home.state.HomeAction +import app.dapk.st.home.state.HomeEvent +import app.dapk.st.home.state.HomeState import app.dapk.st.state.state import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach class MainActivity : DapkActivity() { - private val directoryState by state { module().directoryState() } - private val loginState by state { module().loginState() } - private val profileState by state { module().profileState() } - private val homeViewModel by viewModel { module().homeViewModel(directoryState, loginState, profileState) } + private val homeModule by unsafeLazy { module() } + private val compositeState by state { homeModule.compositeHomeState() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val pushPermissionLauncher = registerPushPermission() - homeViewModel.events.onEach { + compositeState.events.onEach { when (it) { HomeEvent.Relaunch -> recreate() HomeEvent.OnShowContent -> pushPermissionLauncher?.invoke() @@ -39,11 +37,12 @@ class MainActivity : DapkActivity() { }.launchIn(lifecycleScope) setContent { - if (homeViewModel.hasVersionChanged()) { - BetaUpgradeDialog() + val homeState: HomeState = compositeState.childState() + if (homeModule.betaVersionUpgradeUseCase.hasVersionChanged()) { + BetaUpgradeDialog(homeState) } else { Surface(Modifier.fillMaxSize()) { - HomeScreen(homeViewModel, directoryState, loginState, profileState) + HomeScreen(homeState, compositeState.childState(), compositeState.childState(), compositeState.childState()) } } } @@ -56,20 +55,20 @@ class MainActivity : DapkActivity() { null } } - - @Composable - private fun BetaUpgradeDialog() { - AlertDialog( - title = { Text(text = "BETA") }, - text = { Text(text = "During the BETA, version upgrades require a cache clear") }, - onDismissRequest = { - - }, - confirmButton = { - TextButton(onClick = { homeViewModel.clearCache() }) { - Text(text = "Clear cache".uppercase()) - } - }, - ) - } +} + +@Composable +private fun BetaUpgradeDialog(homeState: HomeState) { + AlertDialog( + title = { Text(text = "BETA") }, + text = { Text(text = "During the BETA, version upgrades require a cache clear") }, + onDismissRequest = { + + }, + confirmButton = { + TextButton(onClick = { homeState.dispatch(HomeAction.ClearCache) }) { + Text(text = "Clear cache".uppercase()) + } + }, + ) } diff --git a/features/home/src/main/kotlin/app/dapk/st/home/state/CreateHomeReducer.kt b/features/home/src/main/kotlin/app/dapk/st/home/state/CreateHomeReducer.kt new file mode 100644 index 0000000..f330c67 --- /dev/null +++ b/features/home/src/main/kotlin/app/dapk/st/home/state/CreateHomeReducer.kt @@ -0,0 +1,116 @@ +package app.dapk.st.home.state + +import app.dapk.st.core.JobBag +import app.dapk.st.directory.state.ComponentLifecycle +import app.dapk.st.directory.state.DirectorySideEffect +import app.dapk.st.domain.StoreCleaner +import app.dapk.st.engine.ChatEngine +import app.dapk.st.home.BetaVersionUpgradeUseCase +import app.dapk.st.profile.state.ProfileAction +import app.dapk.state.* +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach + +fun createHomeReducer( + chatEngine: ChatEngine, + cacheCleaner: StoreCleaner, + betaVersionUpgradeUseCase: BetaVersionUpgradeUseCase, + jobBag: JobBag, + eventEmitter: suspend (HomeEvent) -> Unit, +): ReducerFactory { + return createReducer( + initialState = HomeScreenState.Loading, + + change(HomeAction.UpdateState::class) { action, _ -> + action.state + }, + + change(HomeAction.UpdateInvitesCount::class) { action, state -> + when (state) { + HomeScreenState.Loading -> state + is HomeScreenState.SignedIn -> state.copy(invites = action.invitesCount) + HomeScreenState.SignedOut -> state + } + }, + + async(HomeAction.LifecycleVisible::class) { _ -> + if (chatEngine.isSignedIn()) { + eventEmitter.invoke(HomeEvent.OnShowContent) + dispatch(HomeAction.InitialHome) + listenForInviteChanges(chatEngine, jobBag) + } else { + dispatch(HomeAction.UpdateState(HomeScreenState.SignedOut)) + } + }, + + async(HomeAction.InitialHome::class) { + val me = chatEngine.me(forceRefresh = false) + val nextState = when (val current = getState()) { + HomeScreenState.Loading -> HomeScreenState.SignedIn(HomeScreenState.Page.Directory, me, invites = 0) + is HomeScreenState.SignedIn -> current.copy(me = me, invites = current.invites) + HomeScreenState.SignedOut -> HomeScreenState.SignedIn(HomeScreenState.Page.Directory, me, invites = 0) + } + dispatch(HomeAction.UpdateState(nextState)) + }, + + async(HomeAction.LoggedIn::class) { + dispatch(HomeAction.InitialHome) + eventEmitter.invoke(HomeEvent.OnShowContent) + listenForInviteChanges(chatEngine, jobBag) + }, + + multi(HomeAction.ChangePage::class) { action -> + change { _, state -> + when (state) { + is HomeScreenState.SignedIn -> when (action.page) { + state.page -> state + else -> state.copy(page = action.page).also { + async { + when (action.page) { + HomeScreenState.Page.Directory -> { + // do nothing + } + + HomeScreenState.Page.Profile -> { + dispatch(ComponentLifecycle.OnGone) + dispatch(ProfileAction.Reset) + } + } + } + } + } + + HomeScreenState.Loading -> state + HomeScreenState.SignedOut -> state + } + } + }, + + async(HomeAction.ScrollToTop::class) { + dispatch(DirectorySideEffect.ScrollToTop) + }, + + + sideEffect(HomeAction.ClearCache::class) { _, _ -> + cacheCleaner.cleanCache(removeCredentials = false) + betaVersionUpgradeUseCase.notifyUpgraded() + eventEmitter.invoke(HomeEvent.Relaunch) + } + ) +} + +private fun ReducerScope.listenForInviteChanges(chatEngine: ChatEngine, jobBag: JobBag) { + jobBag.replace( + "invites-count", + chatEngine.invites() + .onEach { invites -> + when (getState()) { + is HomeScreenState.SignedIn -> dispatch(HomeAction.UpdateInvitesCount(invites.size)) + HomeScreenState.Loading, + HomeScreenState.SignedOut -> { + // do nothing + } + } + }.launchIn(coroutineScope) + ) +} \ No newline at end of file diff --git a/features/home/src/main/kotlin/app/dapk/st/home/state/HomeAction.kt b/features/home/src/main/kotlin/app/dapk/st/home/state/HomeAction.kt new file mode 100644 index 0000000..25bc9cd --- /dev/null +++ b/features/home/src/main/kotlin/app/dapk/st/home/state/HomeAction.kt @@ -0,0 +1,18 @@ +package app.dapk.st.home.state + +import app.dapk.st.home.state.HomeScreenState.Page +import app.dapk.state.Action + +sealed interface HomeAction : Action { + object LifecycleVisible : HomeAction + object LifecycleGone : HomeAction + + object ScrollToTop : HomeAction + object ClearCache : HomeAction + object LoggedIn : HomeAction + + data class ChangePage(val page: Page) : HomeAction + data class UpdateInvitesCount(val invitesCount: Int) : HomeAction + data class UpdateState(val state: HomeScreenState) : HomeAction + object InitialHome : HomeAction +} diff --git a/features/home/src/main/kotlin/app/dapk/st/home/HomeState.kt b/features/home/src/main/kotlin/app/dapk/st/home/state/HomeState.kt similarity index 84% rename from features/home/src/main/kotlin/app/dapk/st/home/HomeState.kt rename to features/home/src/main/kotlin/app/dapk/st/home/state/HomeState.kt index 22ec6aa..151ae60 100644 --- a/features/home/src/main/kotlin/app/dapk/st/home/HomeState.kt +++ b/features/home/src/main/kotlin/app/dapk/st/home/state/HomeState.kt @@ -1,10 +1,13 @@ -package app.dapk.st.home +package app.dapk.st.home.state import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.Settings import androidx.compose.ui.graphics.vector.ImageVector import app.dapk.st.engine.Me +import app.dapk.st.state.State + +typealias HomeState = State sealed interface HomeScreenState { diff --git a/features/login/src/main/kotlin/app/dapk/st/login/LoginModule.kt b/features/login/src/main/kotlin/app/dapk/st/login/LoginModule.kt index 34251e7..b3bf5b6 100644 --- a/features/login/src/main/kotlin/app/dapk/st/login/LoginModule.kt +++ b/features/login/src/main/kotlin/app/dapk/st/login/LoginModule.kt @@ -3,11 +3,10 @@ package app.dapk.st.login import app.dapk.st.core.ProvidableModule import app.dapk.st.core.extensions.ErrorTracker import app.dapk.st.engine.ChatEngine -import app.dapk.st.login.state.LoginState -import app.dapk.st.login.state.LoginUseCase -import app.dapk.st.login.state.loginReducer +import app.dapk.st.login.state.* import app.dapk.st.push.PushModule import app.dapk.st.state.createStateViewModel +import app.dapk.state.ReducerFactory class LoginModule( private val chatEngine: ChatEngine, @@ -17,8 +16,12 @@ class LoginModule( fun loginState(): LoginState { return createStateViewModel { - val loginUseCase = LoginUseCase(chatEngine, pushModule.pushTokenRegistrars(), errorTracker) - loginReducer(loginUseCase, it) + loginReducer(it) } } + + fun loginReducer(eventEmitter: suspend (LoginEvent) -> Unit): ReducerFactory { + val loginUseCase = LoginUseCase(chatEngine, pushModule.pushTokenRegistrars(), errorTracker) + return loginReducer(loginUseCase, eventEmitter) + } } \ No newline at end of file diff --git a/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileModule.kt b/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileModule.kt index 165f993..f2be4a2 100644 --- a/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileModule.kt +++ b/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileModule.kt @@ -15,7 +15,9 @@ class ProfileModule( ) : ProvidableModule { fun profileState(): ProfileState { - return createStateViewModel { profileReducer(chatEngine, errorTracker, ProfileUseCase(chatEngine, errorTracker), JobBag()) } + return createStateViewModel { profileReducer() } } + fun profileReducer() = profileReducer(chatEngine, errorTracker, ProfileUseCase(chatEngine, errorTracker), JobBag()) + } \ No newline at end of file diff --git a/screen-state b/screen-state index a0425cb..9abb6b4 160000 --- a/screen-state +++ b/screen-state @@ -1 +1 @@ -Subproject commit a0425cb9196ba728309b1f2ab616df6ad1168b90 +Subproject commit 9abb6b4418f451d81f09c4ba2b26f2b1ffd19f55