Browse Source

Other way of observing form state

feature/bma/flipper
ganfra 2 years ago
parent
commit
3e6c3d0397
  1. 21
      features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt
  2. 30
      features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt
  3. 17
      features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt

21
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.Success
import com.airbnb.mvrx.compose.collectAsState import com.airbnb.mvrx.compose.collectAsState
import com.airbnb.mvrx.compose.mavericksViewModel import com.airbnb.mvrx.compose.mavericksViewModel
import io.element.android.x.core.compose.textFieldState
import io.element.android.x.designsystem.ElementXTheme import io.element.android.x.designsystem.ElementXTheme
import timber.log.Timber import timber.log.Timber
@ -39,12 +38,14 @@ fun LoginScreen(
onLoginWithSuccess: () -> Unit = { }, onLoginWithSuccess: () -> Unit = { },
) { ) {
val state: LoginViewState by viewModel.collectAsState() val state: LoginViewState by viewModel.collectAsState()
val formState: LoginFormState by viewModel.formState
LaunchedEffect(key1 = Unit) { LaunchedEffect(key1 = Unit) {
Timber.d("resume") Timber.d("resume")
viewModel.onResume() viewModel.onResume()
} }
LoginContent( LoginContent(
state = state, state = state,
formState = formState,
onChangeServer = onChangeServer, onChangeServer = onChangeServer,
onLoginChanged = viewModel::onSetName, onLoginChanged = viewModel::onSetName,
onPasswordChanged = viewModel::onSetPassword, onPasswordChanged = viewModel::onSetPassword,
@ -58,6 +59,7 @@ fun LoginScreen(
@Composable @Composable
fun LoginContent( fun LoginContent(
state: LoginViewState, state: LoginViewState,
formState: LoginFormState,
onChangeServer: () -> Unit = {}, onChangeServer: () -> Unit = {},
onLoginChanged: (String) -> Unit = {}, onLoginChanged: (String) -> Unit = {},
onPasswordChanged: (String) -> Unit = {}, onPasswordChanged: (String) -> Unit = {},
@ -117,39 +119,31 @@ fun LoginContent(
} }
) )
} }
var login by textFieldState(state.login)
OutlinedTextField( OutlinedTextField(
value = login, value = formState.login,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 60.dp), .padding(top = 60.dp),
label = { label = {
Text(text = "Email or username") Text(text = "Email or username")
}, },
onValueChange = { onValueChange = onLoginChanged,
login = it
onLoginChanged(it)
},
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email, keyboardType = KeyboardType.Email,
imeAction = ImeAction.Next imeAction = ImeAction.Next
), ),
) )
var passwordVisible by remember { mutableStateOf(false) } var passwordVisible by remember { mutableStateOf(false) }
var password by textFieldState(state.password)
if (state.isLoggedIn is Loading) { if (state.isLoggedIn is Loading) {
// Ensure password is hidden when user submits the form // Ensure password is hidden when user submits the form
passwordVisible = false passwordVisible = false
} }
OutlinedTextField( OutlinedTextField(
value = password, value = formState.password,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 24.dp), .padding(top = 24.dp),
onValueChange = { onValueChange = onPasswordChanged,
password = it
onPasswordChanged(it)
},
label = { label = {
Text(text = "Password") Text(text = "Password")
}, },
@ -213,6 +207,7 @@ private fun LoginContentPreview() {
state = LoginViewState( state = LoginViewState(
homeserver = "matrix.org", homeserver = "matrix.org",
), ),
formState = LoginFormState("", "")
) )
} }
} }

30
features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt

@ -1,14 +1,26 @@
package io.element.android.x.features.login 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.MavericksViewModel
import com.airbnb.mvrx.Uninitialized
import io.element.android.x.matrix.MatrixInstance import io.element.android.x.matrix.MatrixInstance
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class LoginViewModel(initialState: LoginViewState) : class LoginViewModel(initialState: LoginViewState) :
MavericksViewModel<LoginViewState>(initialState) { MavericksViewModel<LoginViewState>(initialState) {
private val matrix = MatrixInstance.getInstance() 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() { fun onResume() {
val currentHomeserver = matrix.getHomeserverOrDefault() val currentHomeserver = matrix.getHomeserverOrDefault()
@ -25,7 +37,7 @@ class LoginViewModel(initialState: LoginViewState) :
val state = awaitState() val state = awaitState()
// Ensure the server is provided to the Rust SDK // Ensure the server is provided to the Rust SDK
matrix.setHomeserver(state.homeserver) 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() matrix.activeClient().startSync()
}.execute { }.execute {
copy(isLoggedIn = it) copy(isLoggedIn = it)
@ -34,20 +46,10 @@ class LoginViewModel(initialState: LoginViewState) :
} }
fun onSetPassword(password: String) { fun onSetPassword(password: String) {
setState { formState.value = formState.value.copy(password = password)
copy(
password = password,
isLoggedIn = Uninitialized,
)
}
} }
fun onSetName(name: String) { fun onSetName(name: String) {
setState { formState.value = formState.value.copy(login = name)
copy(
login = name,
isLoggedIn = Uninitialized,
)
}
} }
} }

17
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( data class LoginViewState(
val homeserver: String = "", val homeserver: String = "",
val login: String = "",
val password: String = "",
val isLoggedIn: Async<Unit> = Uninitialized, val isLoggedIn: Async<Unit> = Uninitialized,
val formState: LoginFormState = LoginFormState.Default,
) : MavericksState { ) : 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("", "")
}
}
Loading…
Cancel
Save