Other way of observing form state
This commit is contained in:
@@ -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("", "")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<LoginViewState>(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)
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,20 @@ import com.airbnb.mvrx.Uninitialized
|
||||
|
||||
data class LoginViewState(
|
||||
val homeserver: String = "",
|
||||
val login: String = "",
|
||||
val password: String = "",
|
||||
val isLoggedIn: Async<Unit> = 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("", "")
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user