Introduce SessionComponent

This commit is contained in:
ganfra 2022-12-16 17:24:55 +01:00
parent eba807e37a
commit 0a06ca0539
18 changed files with 176 additions and 104 deletions

View file

@ -30,13 +30,14 @@ import com.airbnb.mvrx.compose.collectAsState
import com.airbnb.mvrx.compose.mavericksViewModel
import io.element.android.x.designsystem.ElementXTheme
import io.element.android.x.features.login.error.loginError
import io.element.android.x.matrix.MatrixClient
import timber.log.Timber
@Composable
fun LoginScreen(
viewModel: LoginViewModel = mavericksViewModel(),
onChangeServer: () -> Unit = { },
onLoginWithSuccess: () -> Unit = { },
onLoginWithSuccess: (MatrixClient) -> Unit = { },
) {
val state: LoginViewState by viewModel.collectAsState()
val formState: LoginFormState by viewModel.formState
@ -65,7 +66,7 @@ fun LoginContent(
onLoginChanged: (String) -> Unit = {},
onPasswordChanged: (String) -> Unit = {},
onSubmitClicked: () -> Unit = {},
onLoginWithSuccess: () -> Unit = {},
onLoginWithSuccess: (MatrixClient) -> Unit = {},
) {
Surface(color = MaterialTheme.colorScheme.background) {
Box(
@ -82,7 +83,7 @@ fun LoginContent(
)
.padding(horizontal = 16.dp),
) {
val isError = state.isLoggedIn is Fail
val isError = state.loggedInClient is Fail
// Title
Text(
text = "Welcome back",
@ -137,7 +138,7 @@ fun LoginContent(
),
)
var passwordVisible by remember { mutableStateOf(false) }
if (state.isLoggedIn is Loading) {
if (state.loggedInClient is Loading) {
// Ensure password is hidden when user submits the form
passwordVisible = false
}
@ -170,9 +171,9 @@ fun LoginContent(
onDone = { onSubmitClicked() }
),
)
if (state.isLoggedIn is Fail) {
if (state.loggedInClient is Fail) {
Text(
text = loginError(state.formState, state.isLoggedIn.error),
text = loginError(state.formState, state.loggedInClient.error),
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(start = 16.dp)
@ -189,11 +190,12 @@ fun LoginContent(
) {
Text(text = "Continue")
}
if (state.isLoggedIn is Success) {
onLoginWithSuccess()
when (val loggedInClient = state.loggedInClient) {
is Success -> onLoginWithSuccess(loggedInClient())
else -> Unit
}
}
if (state.isLoggedIn is Loading) {
if (state.loggedInClient is Loading) {
CircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
)

View file

@ -11,7 +11,6 @@ import io.element.android.x.anvilannotations.ContributesViewModel
import io.element.android.x.core.di.daggerMavericksViewModelFactory
import io.element.android.x.di.AppScope
import io.element.android.x.matrix.Matrix
import io.element.android.x.matrix.MatrixInstance
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -49,21 +48,22 @@ class LoginViewModel @AssistedInject constructor(
val state = awaitState()
// Ensure the server is provided to the Rust SDK
matrix.setHomeserver(state.homeserver)
matrix.login(state.formState.login.trim(), state.formState.password.trim())
matrix.activeClient().startSync()
matrix.login(state.formState.login.trim(), state.formState.password.trim()).also {
it.startSync()
}
}.execute {
copy(isLoggedIn = it)
copy(loggedInClient = it)
}
}
}
fun onSetPassword(password: String) {
formState.value = formState.value.copy(password = password)
setState { copy(isLoggedIn = Uninitialized) }
setState { copy(loggedInClient = Uninitialized) }
}
fun onSetName(name: String) {
formState.value = formState.value.copy(login = name)
setState { copy(isLoggedIn = Uninitialized) }
setState { copy(loggedInClient = Uninitialized) }
}
}

View file

@ -4,14 +4,15 @@ import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.Uninitialized
import io.element.android.x.matrix.MatrixClient
data class LoginViewState(
val homeserver: String = "",
val isLoggedIn: Async<Unit> = Uninitialized,
val loggedInClient: Async<MatrixClient> = Uninitialized,
val formState: LoginFormState = LoginFormState.Default,
) : MavericksState {
val submitEnabled =
formState.login.isNotEmpty() && formState.password.isNotEmpty() && isLoggedIn !is Loading
formState.login.isNotEmpty() && formState.password.isNotEmpty() && loggedInClient !is Loading
}
data class LoginFormState(

View file

@ -1,14 +1,25 @@
package io.element.android.x.features.login.changeserver
import com.airbnb.mvrx.MavericksViewModel
import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.Uninitialized
import io.element.android.x.matrix.MatrixInstance
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.x.anvilannotations.ContributesViewModel
import io.element.android.x.core.di.daggerMavericksViewModelFactory
import io.element.android.x.di.AppScope
import io.element.android.x.matrix.Matrix
import kotlinx.coroutines.launch
class ChangeServerViewModel(initialState: ChangeServerViewState) :
@ContributesViewModel(AppScope::class)
class ChangeServerViewModel @AssistedInject constructor(
private val matrix: Matrix,
@Assisted initialState: ChangeServerViewState
) :
MavericksViewModel<ChangeServerViewState>(initialState) {
private val matrix = MatrixInstance.getInstance()
companion object :
MavericksViewModelFactory<ChangeServerViewModel, ChangeServerViewState> by daggerMavericksViewModelFactory()
init {
setState {
@ -32,7 +43,7 @@ class ChangeServerViewModel(initialState: ChangeServerViewState) :
suspend {
val state = awaitState()
matrix.setHomeserver(state.homeserver)
}.execute { it ->
}.execute {
copy(changeServerAction = it)
}
}

View file

@ -10,6 +10,7 @@ import io.element.android.x.core.di.daggerMavericksViewModelFactory
import io.element.android.x.designsystem.components.avatar.AvatarData
import io.element.android.x.designsystem.components.avatar.AvatarSize
import io.element.android.x.di.AppScope
import io.element.android.x.di.SessionScope
import io.element.android.x.features.messages.model.MessagesItemAction
import io.element.android.x.features.messages.model.MessagesItemActionsSheetState
import io.element.android.x.features.messages.model.MessagesTimelineItemState
@ -17,6 +18,7 @@ import io.element.android.x.features.messages.model.MessagesViewState
import io.element.android.x.features.messages.model.content.MessagesTimelineItemRedactedContent
import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextBasedContent
import io.element.android.x.matrix.Matrix
import io.element.android.x.matrix.MatrixClient
import io.element.android.x.matrix.media.MediaResolver
import io.element.android.x.matrix.timeline.MatrixTimeline
import io.element.android.x.matrix.timeline.MatrixTimelineItem
@ -28,16 +30,15 @@ import kotlinx.coroutines.launch
private const val PAGINATION_COUNT = 50
@ContributesViewModel(AppScope::class)
@ContributesViewModel(SessionScope::class)
class MessagesViewModel @AssistedInject constructor(
matrix: Matrix,
private val client: MatrixClient,
@Assisted private val initialState: MessagesViewState
) :
MavericksViewModel<MessagesViewState>(initialState) {
companion object : MavericksViewModelFactory<MessagesViewModel, MessagesViewState> by daggerMavericksViewModelFactory()
private val client = matrix.activeClient()
private val room = client.getRoom(initialState.roomId)!!
private val messageTimelineItemStateFactory =
MessageTimelineItemStateFactory(client, room, Dispatchers.Default)

View file

@ -7,20 +7,18 @@ import dagger.assisted.AssistedInject
import io.element.android.x.anvilannotations.ContributesViewModel
import io.element.android.x.core.data.StableCharSequence
import io.element.android.x.core.di.daggerMavericksViewModelFactory
import io.element.android.x.di.AppScope
import io.element.android.x.matrix.Matrix
import io.element.android.x.di.SessionScope
import io.element.android.x.matrix.MatrixClient
@ContributesViewModel(AppScope::class)
@ContributesViewModel(SessionScope::class)
class MessageComposerViewModel @AssistedInject constructor(
private val matrix: Matrix,
private val client: MatrixClient,
@Assisted private val initialState: MessageComposerViewState
) : MavericksViewModel<MessageComposerViewState>(initialState) {
companion object :
MavericksViewModelFactory<MessageComposerViewModel, MessageComposerViewState> by daggerMavericksViewModelFactory()
private val client = matrix.activeClient()
fun onComposerFullScreenChange() {
setState {
copy(

View file

@ -9,13 +9,13 @@ import io.element.android.x.core.di.daggerMavericksViewModelFactory
import io.element.android.x.designsystem.components.avatar.AvatarData
import io.element.android.x.designsystem.components.avatar.AvatarSize
import io.element.android.x.di.AppScope
import io.element.android.x.di.SessionScope
import io.element.android.x.features.roomlist.model.MatrixUser
import io.element.android.x.features.roomlist.model.RoomListRoomSummary
import io.element.android.x.features.roomlist.model.RoomListRoomSummaryPlaceholders
import io.element.android.x.features.roomlist.model.RoomListViewState
import io.element.android.x.matrix.Matrix
import io.element.android.x.matrix.MatrixClient
import io.element.android.x.matrix.MatrixInstance
import io.element.android.x.matrix.media.MediaResolver
import io.element.android.x.matrix.room.RoomSummary
import kotlinx.coroutines.Dispatchers
@ -28,9 +28,9 @@ import kotlinx.coroutines.launch
private const val extendedRangeSize = 40
@ContributesViewModel(AppScope::class)
@ContributesViewModel(SessionScope::class)
class RoomListViewModel @AssistedInject constructor(
matrix: Matrix,
private val client: MatrixClient,
@Assisted initialState: RoomListViewState
) :
MavericksViewModel<RoomListViewState>(initialState) {
@ -38,7 +38,6 @@ class RoomListViewModel @AssistedInject constructor(
companion object : MavericksViewModelFactory<RoomListViewModel, RoomListViewState> by daggerMavericksViewModelFactory()
private val lastMessageFormatter = LastMessageFormatter()
private val client = matrix.activeClient()
init {
handleInit()