From 3e6c3d0397b4b8355ba7482235c643bd40e3a26c Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 22 Nov 2022 12:56:37 +0100 Subject: [PATCH] Other way of observing form state --- .../android/x/features/login/LoginScreen.kt | 21 +++++-------- .../x/features/login/LoginViewModel.kt | 30 ++++++++++--------- .../x/features/login/LoginViewState.kt | 17 +++++++++-- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt index 8ac71ab9c9..a9afc11326 100644 --- a/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt +++ b/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt @@ -28,7 +28,6 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.compose.collectAsState import com.airbnb.mvrx.compose.mavericksViewModel -import io.element.android.x.core.compose.textFieldState import io.element.android.x.designsystem.ElementXTheme import timber.log.Timber @@ -39,12 +38,14 @@ fun LoginScreen( onLoginWithSuccess: () -> Unit = { }, ) { val state: LoginViewState by viewModel.collectAsState() + val formState: LoginFormState by viewModel.formState LaunchedEffect(key1 = Unit) { Timber.d("resume") viewModel.onResume() } LoginContent( state = state, + formState = formState, onChangeServer = onChangeServer, onLoginChanged = viewModel::onSetName, onPasswordChanged = viewModel::onSetPassword, @@ -58,6 +59,7 @@ fun LoginScreen( @Composable fun LoginContent( state: LoginViewState, + formState: LoginFormState, onChangeServer: () -> Unit = {}, onLoginChanged: (String) -> Unit = {}, onPasswordChanged: (String) -> Unit = {}, @@ -117,39 +119,31 @@ fun LoginContent( } ) } - var login by textFieldState(state.login) OutlinedTextField( - value = login, + value = formState.login, modifier = Modifier .fillMaxWidth() .padding(top = 60.dp), label = { Text(text = "Email or username") }, - onValueChange = { - login = it - onLoginChanged(it) - }, + onValueChange = onLoginChanged, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Email, imeAction = ImeAction.Next ), ) var passwordVisible by remember { mutableStateOf(false) } - var password by textFieldState(state.password) if (state.isLoggedIn is Loading) { // Ensure password is hidden when user submits the form passwordVisible = false } OutlinedTextField( - value = password, + value = formState.password, modifier = Modifier .fillMaxWidth() .padding(top = 24.dp), - onValueChange = { - password = it - onPasswordChanged(it) - }, + onValueChange = onPasswordChanged, label = { Text(text = "Password") }, @@ -213,6 +207,7 @@ private fun LoginContentPreview() { state = LoginViewState( homeserver = "matrix.org", ), + formState = LoginFormState("", "") ) } } diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt index c15fc4cf03..ae3164440e 100644 --- a/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt +++ b/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt @@ -1,14 +1,26 @@ package io.element.android.x.features.login +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.snapshotFlow import com.airbnb.mvrx.MavericksViewModel -import com.airbnb.mvrx.Uninitialized import io.element.android.x.matrix.MatrixInstance +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch class LoginViewModel(initialState: LoginViewState) : MavericksViewModel(initialState) { private val matrix = MatrixInstance.getInstance() + var formState = mutableStateOf(LoginFormState.Default) + private set + + init { + snapshotFlow { formState.value } + .onEach { + setState { copy(formState = it) } + }.launchIn(viewModelScope) + } fun onResume() { val currentHomeserver = matrix.getHomeserverOrDefault() @@ -25,7 +37,7 @@ class LoginViewModel(initialState: LoginViewState) : val state = awaitState() // Ensure the server is provided to the Rust SDK matrix.setHomeserver(state.homeserver) - matrix.login(state.login.trim(), state.password.trim()) + matrix.login(state.formState.login.trim(), state.formState.password.trim()) matrix.activeClient().startSync() }.execute { copy(isLoggedIn = it) @@ -34,20 +46,10 @@ class LoginViewModel(initialState: LoginViewState) : } fun onSetPassword(password: String) { - setState { - copy( - password = password, - isLoggedIn = Uninitialized, - ) - } + formState.value = formState.value.copy(password = password) } fun onSetName(name: String) { - setState { - copy( - login = name, - isLoggedIn = Uninitialized, - ) - } + formState.value = formState.value.copy(login = name) } } \ No newline at end of file diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt index 2a92a39e4e..62513cff08 100644 --- a/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt +++ b/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt @@ -7,9 +7,20 @@ import com.airbnb.mvrx.Uninitialized data class LoginViewState( val homeserver: String = "", - val login: String = "", - val password: String = "", val isLoggedIn: Async = Uninitialized, + val formState: LoginFormState = LoginFormState.Default, ) : MavericksState { - val submitEnabled = login.isNotEmpty() && password.isNotEmpty() && isLoggedIn !is Loading + val submitEnabled = + formState.login.isNotEmpty() && formState.password.isNotEmpty() && isLoggedIn !is Loading } + +data class LoginFormState( + val login: String, + val password: String +) { + + companion object { + val Default = LoginFormState("", "") + } + +} \ No newline at end of file