Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Porting ProfileViewModel to reducer #260

Merged
merged 2 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions chat-engine/src/testFixtures/kotlin/fake/FakeChatEngine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,10 @@ import java.io.InputStream
class FakeChatEngine : ChatEngine by mockk() {

fun givenMessages(roomId: RoomId, disableReadReceipts: Boolean) = every { messages(roomId, disableReadReceipts) }.delegateReturn()

fun givenDirectory() = every { directory() }.delegateReturn()

fun givenImportKeys(inputStream: InputStream, passphrase: String) = coEvery { inputStream.importRoomKeys(passphrase) }.delegateReturn()

fun givenNotificationsInvites() = every { notificationsInvites() }.delegateEmit()

fun givenNotificationsMessages() = every { notificationsMessages() }.delegateEmit()

fun givenInvites() = every { invites() }.delegateEmit()
fun givenMe(forceRefresh: Boolean) = coEvery { me(forceRefresh) }.delegateReturn()
}
4 changes: 4 additions & 0 deletions core/src/main/kotlin/app/dapk/st/core/JobBag.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ class JobBag {
jobs.remove(key.java.canonicalName)?.cancel()
}

fun cancelAll() {
jobs.values.forEach { it.cancel() }
}

}
2 changes: 0 additions & 2 deletions features/directory/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ applyAndroidComposeLibraryModule(project)
dependencies {
implementation project(":chat-engine")
implementation project(":domains:android:compose-core")
implementation project(":domains:android:viewmodel")
implementation project(":domains:state")
implementation project(":features:messenger")
implementation project(":core")
Expand All @@ -16,7 +15,6 @@ dependencies {
androidImportFixturesWorkaround(project, project(":core"))
androidImportFixturesWorkaround(project, project(":domains:state"))
androidImportFixturesWorkaround(project, project(":domains:store"))
androidImportFixturesWorkaround(project, project(":domains:android:viewmodel"))
androidImportFixturesWorkaround(project, project(":domains:android:stub"))
androidImportFixturesWorkaround(project, project(":chat-engine"))
}
6 changes: 3 additions & 3 deletions features/home/src/main/kotlin/app/dapk/st/home/HomeModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import app.dapk.st.directory.state.DirectoryState
import app.dapk.st.domain.StoreModule
import app.dapk.st.engine.ChatEngine
import app.dapk.st.login.LoginViewModel
import app.dapk.st.profile.ProfileViewModel
import app.dapk.st.profile.state.ProfileState

class HomeModule(
private val chatEngine: ChatEngine,
private val storeModule: StoreModule,
val betaVersionUpgradeUseCase: BetaVersionUpgradeUseCase,
) : ProvidableModule {

internal fun homeViewModel(directory: DirectoryState, login: LoginViewModel, profileViewModel: ProfileViewModel): HomeViewModel {
internal fun homeViewModel(directory: DirectoryState, login: LoginViewModel, profile: ProfileState): HomeViewModel {
return HomeViewModel(
chatEngine,
storeModule.credentialsStore(),
directory,
login,
profileViewModel,
profile,
storeModule.cacheCleaner(),
betaVersionUpgradeUseCase,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import app.dapk.st.home.HomeScreenState.*
import app.dapk.st.login.LoginViewModel
import app.dapk.st.matrix.common.CredentialsStore
import app.dapk.st.matrix.common.isSignedIn
import app.dapk.st.profile.ProfileViewModel
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
Expand All @@ -24,7 +25,7 @@ internal class HomeViewModel(
private val credentialsProvider: CredentialsStore,
private val directoryState: DirectoryState,
private val loginViewModel: LoginViewModel,
private val profileViewModel: ProfileViewModel,
private val profileState: ProfileState,
private val cacheCleaner: StoreCleaner,
private val betaVersionUpgradeUseCase: BetaVersionUpgradeUseCase,
) : DapkViewModel<HomeScreenState, HomeEvent>(
Expand All @@ -35,7 +36,7 @@ internal class HomeViewModel(

fun directory() = directoryState
fun login() = loginViewModel
fun profile() = profileViewModel
fun profile() = profileState

fun start() {
viewModelScope.launch {
Expand Down Expand Up @@ -125,7 +126,7 @@ internal class HomeViewModel(

Page.Profile -> {
directoryState.dispatch(ComponentLifecycle.OnGone)
profileViewModel.reset()
profileState.dispatch(ProfileAction.Reset)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class MainActivity : DapkActivity() {

private val directoryViewModel by state { module<DirectoryModule>().directoryState() }
private val loginViewModel by viewModel { module<LoginModule>().loginViewModel() }
private val profileViewModel by viewModel { module<ProfileModule>().profileViewModel() }
private val profileViewModel by state { module<ProfileModule>().profileState() }
private val homeViewModel by viewModel { module<HomeModule>().homeViewModel(directoryViewModel, loginViewModel, profileViewModel) }

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down
11 changes: 10 additions & 1 deletion features/profile/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ dependencies {
implementation project(":chat-engine")
implementation project(":features:settings")
implementation project(':domains:store')
implementation project(':domains:state')
implementation project(":domains:android:compose-core")
implementation project(":domains:android:viewmodel")
implementation project(":design-library")
implementation project(":core")

kotlinTest(it)

androidImportFixturesWorkaround(project, project(":matrix:common"))
androidImportFixturesWorkaround(project, project(":core"))
androidImportFixturesWorkaround(project, project(":domains:state"))
androidImportFixturesWorkaround(project, project(":domains:store"))
androidImportFixturesWorkaround(project, project(":domains:android:stub"))
androidImportFixturesWorkaround(project, project(":chat-engine"))
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package app.dapk.st.profile

import app.dapk.st.core.JobBag
import app.dapk.st.core.ProvidableModule
import app.dapk.st.core.createStateViewModel
import app.dapk.st.core.extensions.ErrorTracker
import app.dapk.st.engine.ChatEngine
import app.dapk.st.profile.state.ProfileState
import app.dapk.st.profile.state.ProfileUseCase
import app.dapk.st.profile.state.profileReducer

class ProfileModule(
private val chatEngine: ChatEngine,
private val errorTracker: ErrorTracker,
) : ProvidableModule {

fun profileViewModel(): ProfileViewModel {
return ProfileViewModel(chatEngine, errorTracker)
fun profileState(): ProfileState {
return createStateViewModel { profileReducer(chatEngine, errorTracker, ProfileUseCase(chatEngine, errorTracker), JobBag()) }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,34 @@ import androidx.compose.ui.unit.dp
import app.dapk.st.core.Lce
import app.dapk.st.core.LifecycleEffect
import app.dapk.st.core.components.CenteredLoading
import app.dapk.st.core.page.PageAction
import app.dapk.st.design.components.*
import app.dapk.st.engine.RoomInvite
import app.dapk.st.engine.RoomInvite.InviteMeta
import app.dapk.st.profile.state.Page
import app.dapk.st.profile.state.ProfileAction
import app.dapk.st.profile.state.ProfileState
import app.dapk.st.settings.SettingsActivity

@Composable
fun ProfileScreen(viewModel: ProfileViewModel, onTopLevelBack: () -> Unit) {
fun ProfileScreen(viewModel: ProfileState, onTopLevelBack: () -> Unit) {
viewModel.ObserveEvents()

LifecycleEffect(
onStart = { viewModel.start() },
onStop = { viewModel.stop() }
onStart = { viewModel.dispatch(ProfileAction.ComponentLifecycle.Visible) },
onStop = { viewModel.dispatch(ProfileAction.ComponentLifecycle.Gone) }
)

val context = LocalContext.current

val onNavigate: (SpiderPage<out Page>?) -> Unit = {
when (it) {
null -> onTopLevelBack()
else -> viewModel.goTo(it)
else -> viewModel.dispatch(PageAction.GoTo(it))
}
}

Spider(currentPage = viewModel.state.page, onNavigate = onNavigate) {
Spider(currentPage = viewModel.current.state1.page, onNavigate = onNavigate) {
item(Page.Routes.profile) {
ProfilePage(context, viewModel, it)
}
Expand All @@ -54,7 +58,7 @@ fun ProfileScreen(viewModel: ProfileViewModel, onTopLevelBack: () -> Unit) {
}

@Composable
private fun ProfilePage(context: Context, viewModel: ProfileViewModel, profile: Page.Profile) {
private fun ProfilePage(context: Context, viewModel: ProfileState, profile: Page.Profile) {
Box(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -67,7 +71,7 @@ private fun ProfilePage(context: Context, viewModel: ProfileViewModel, profile:

when (val state = profile.content) {
is Lce.Loading -> CenteredLoading()
is Lce.Error -> GenericError { viewModel.start() }
is Lce.Error -> GenericError { viewModel.dispatch(ProfileAction.ComponentLifecycle.Visible) }
is Lce.Content -> {
val configuration = LocalConfiguration.current
val content = state.value
Expand Down Expand Up @@ -111,15 +115,15 @@ private fun ProfilePage(context: Context, viewModel: ProfileViewModel, profile:
TextRow(
title = "Invitations",
content = "${content.invitationsCount} pending",
onClick = { viewModel.goToInvitations() }
onClick = { viewModel.dispatch(ProfileAction.GoToInvitations) }
)
}
}
}
}

@Composable
private fun SpiderItemScope.Invitations(viewModel: ProfileViewModel, invitations: Page.Invitations) {
private fun SpiderItemScope.Invitations(viewModel: ProfileState, invitations: Page.Invitations) {
when (val state = invitations.content) {
is Lce.Loading -> CenteredLoading()
is Lce.Content -> {
Expand All @@ -133,11 +137,11 @@ private fun SpiderItemScope.Invitations(viewModel: ProfileViewModel, invitations
TextRow(title = text, includeDivider = false) {
Spacer(modifier = Modifier.height(4.dp))
Row {
Button(modifier = Modifier.weight(1f), onClick = { viewModel.rejectRoomInvite(it.roomId) }) {
Button(modifier = Modifier.weight(1f), onClick = { viewModel.dispatch(ProfileAction.RejectRoomInvite(it.roomId)) }) {
Text("Reject".uppercase())
}
Spacer(modifier = Modifier.fillMaxWidth(0.1f))
Button(modifier = Modifier.weight(1f), onClick = { viewModel.acceptRoomInvite(it.roomId) }) {
Button(modifier = Modifier.weight(1f), onClick = { viewModel.dispatch(ProfileAction.AcceptRoomInvite(it.roomId)) }) {
Text("Accept".uppercase())
}
}
Expand All @@ -154,7 +158,7 @@ private fun SpiderItemScope.Invitations(viewModel: ProfileViewModel, invitations
private fun RoomInvite.inviterName() = this.from.displayName?.let { "$it (${this.from.id.value})" } ?: this.from.id.value

@Composable
private fun ProfileViewModel.ObserveEvents() {
private fun ProfileState.ObserveEvents() {
// StartObserving {
// this@ObserveEvents.events.launch {
// when (it) {
Expand Down
Loading