mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-16 20:10:04 +03:00
Login screens: handle loading Views and global navigation - WIP
This commit is contained in:
parent
3c93807fe6
commit
c6b0ae63ea
15 changed files with 194 additions and 174 deletions
|
@ -116,6 +116,12 @@ interface FragmentModule {
|
|||
@FragmentKey(LoginFragment::class)
|
||||
fun bindLoginFragment(fragment: LoginFragment): Fragment
|
||||
|
||||
// TODO Add all other Login Fragments
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(LoginServerUrlFormFragment::class)
|
||||
fun bindLoginServerUrlFormFragment(fragment: LoginServerUrlFormFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(LoginSsoFallbackFragment::class)
|
||||
|
@ -195,10 +201,4 @@ interface FragmentModule {
|
|||
@IntoMap
|
||||
@FragmentKey(PublicRoomsFragment::class)
|
||||
fun bindPublicRoomsFragment(fragment: PublicRoomsFragment): Fragment
|
||||
|
||||
// TODO Add all other LoginFragment
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(LoginServerUrlFormFragment::class)
|
||||
fun bindLoginServerUrlFormFragment(fragment: LoginServerUrlFormFragment): Fragment
|
||||
}
|
||||
|
|
|
@ -41,12 +41,19 @@ class ErrorFormatter @Inject constructor(private val stringProvider: StringProvi
|
|||
}
|
||||
}
|
||||
is Failure.ServerError -> {
|
||||
if (throwable.error.code == MatrixError.M_CONSENT_NOT_GIVEN) {
|
||||
// Special case for terms and conditions
|
||||
stringProvider.getString(R.string.error_terms_not_accepted)
|
||||
} else {
|
||||
throwable.error.message.takeIf { it.isNotEmpty() }
|
||||
?: throwable.error.code.takeIf { it.isNotEmpty() }
|
||||
when {
|
||||
throwable.error.code == MatrixError.M_CONSENT_NOT_GIVEN -> {
|
||||
// Special case for terms and conditions
|
||||
stringProvider.getString(R.string.error_terms_not_accepted)
|
||||
}
|
||||
throwable.error.code == MatrixError.FORBIDDEN
|
||||
&& throwable.error.message == "Invalid password" -> {
|
||||
stringProvider.getString(R.string.auth_invalid_login_param)
|
||||
}
|
||||
else -> {
|
||||
throwable.error.message.takeIf { it.isNotEmpty() }
|
||||
?: throwable.error.code.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> throwable.localizedMessage
|
||||
|
|
|
@ -18,6 +18,8 @@ package im.vector.riotx.features.login
|
|||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.viewModel
|
||||
|
@ -29,8 +31,12 @@ import im.vector.riotx.core.extensions.addFragmentToBackstack
|
|||
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||
import im.vector.riotx.features.disclaimer.showDisclaimerDialog
|
||||
import im.vector.riotx.features.home.HomeActivity
|
||||
import kotlinx.android.synthetic.main.activity_login.*
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* The LoginActivity manages the fragment navigation and also display the loading View
|
||||
*/
|
||||
class LoginActivity : VectorBaseActivity() {
|
||||
|
||||
private val loginViewModel: LoginViewModel by viewModel()
|
||||
|
@ -42,16 +48,17 @@ class LoginActivity : VectorBaseActivity() {
|
|||
injector.inject(this)
|
||||
}
|
||||
|
||||
override fun getLayoutRes() = R.layout.activity_simple
|
||||
override fun getLayoutRes() = R.layout.activity_login
|
||||
|
||||
override fun initUiAndData() {
|
||||
if (isFirstCreation()) {
|
||||
addFragment(R.id.simpleFragmentContainer, LoginSplashFragment::class.java)
|
||||
addFragment(R.id.loginFragmentContainer, LoginSplashFragment::class.java)
|
||||
}
|
||||
|
||||
// Get config extra
|
||||
val loginConfig = intent.getParcelableExtra<LoginConfig?>(EXTRA_CONFIG)
|
||||
if (loginConfig != null && isFirstCreation()) {
|
||||
// TODO Check this
|
||||
loginViewModel.handle(LoginAction.InitWith(loginConfig))
|
||||
}
|
||||
|
||||
|
@ -59,29 +66,59 @@ class LoginActivity : VectorBaseActivity() {
|
|||
loginSharedActionViewModel.observe()
|
||||
.subscribe {
|
||||
when (it) {
|
||||
is LoginNavigation.OpenServerSelection -> addFragmentToBackstack(R.id.simpleFragmentContainer, LoginServerSelectionFragment::class.java)
|
||||
is LoginNavigation.OnServerSelectionDone -> onServerSelectionDone()
|
||||
is LoginNavigation.OnSignModeSelected -> onSignModeSelected(it)
|
||||
is LoginNavigation.OpenSsoLoginFallback -> addFragmentToBackstack(R.id.simpleFragmentContainer, LoginSsoFallbackFragment::class.java)
|
||||
is LoginNavigation.GoBack -> supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||
is LoginNavigation.OpenServerSelection -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginServerSelectionFragment::class.java)
|
||||
is LoginNavigation.OnServerSelectionDone -> onServerSelectionDone()
|
||||
is LoginNavigation.OnSignModeSelected -> onSignModeSelected(it)
|
||||
is LoginNavigation.OnLoginFlowRetrieved -> onLoginFlowRetrieved(it)
|
||||
is LoginNavigation.OnSsoLoginFallbackError -> onSsoLoginFallbackError(it)
|
||||
}
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
|
||||
loginViewModel.selectSubscribe(this, LoginViewState::asyncLoginAction) {
|
||||
if (it is Success) {
|
||||
val intent = HomeActivity.newIntent(this)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
loginViewModel
|
||||
.subscribe(this) {
|
||||
updateWithState(it)
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
}
|
||||
|
||||
private fun onLoginFlowRetrieved(onLoginFlowRetrieved: LoginNavigation.OnLoginFlowRetrieved) {
|
||||
when (onLoginFlowRetrieved.loginMode) {
|
||||
LoginMode.Sso -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginSsoFallbackFragment::class.java)
|
||||
LoginMode.Unsupported,
|
||||
LoginMode.Password -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginSignUpSignInSelectionFragment::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWithState(loginViewState: LoginViewState) {
|
||||
if (loginViewState.asyncLoginAction is Success) {
|
||||
val intent = HomeActivity.newIntent(this)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
// Loading
|
||||
loginLoading.isVisible = loginViewState.isLoading()
|
||||
}
|
||||
|
||||
private fun onSsoLoginFallbackError(onSsoLoginFallbackError: LoginNavigation.OnSsoLoginFallbackError) {
|
||||
// Pop the backstack
|
||||
supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||
|
||||
// And inform the user
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(getString(R.string.login_sso_error_message, onSsoLoginFallbackError.description, onSsoLoginFallbackError.errorCode))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun onServerSelectionDone() = withState(loginViewModel) {
|
||||
when (it.serverType) {
|
||||
ServerType.MatrixOrg -> addFragmentToBackstack(R.id.simpleFragmentContainer, LoginSignUpSignInSelectionFragment::class.java)
|
||||
ServerType.MatrixOrg -> Unit // In this case, we wait for the login flow
|
||||
ServerType.Modular,
|
||||
ServerType.Other -> addFragmentToBackstack(R.id.simpleFragmentContainer, LoginServerUrlFormFragment::class.java)
|
||||
ServerType.Other -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginServerUrlFormFragment::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,8 +126,8 @@ class LoginActivity : VectorBaseActivity() {
|
|||
// We cannot use the state, it is not ready...
|
||||
when (mode.signMode) {
|
||||
SignMode.Unknown -> error("Sign mode has to be set before calling this method")
|
||||
SignMode.SignUp -> Unit // TODO addFragmentToBackstack(R.id.simpleFragmentContainer, SignUpFragment::class.java)
|
||||
SignMode.SignIn -> addFragmentToBackstack(R.id.simpleFragmentContainer, LoginFragment::class.java)
|
||||
SignMode.SignUp -> Unit // TODO addFragmentToBackstack(R.id.loginFragmentContainer, SignUpFragment::class.java)
|
||||
SignMode.SignIn -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginFragment::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,14 @@ package im.vector.riotx.features.login
|
|||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionManager
|
||||
import com.airbnb.mvrx.*
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.error.ErrorFormatter
|
||||
import im.vector.riotx.core.extensions.showPassword
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.functions.BiFunction
|
||||
|
@ -35,7 +37,9 @@ import javax.inject.Inject
|
|||
* In this screen, the user is asked for login and password to sign in to a homeserver.
|
||||
* He also can reset his password
|
||||
*/
|
||||
class LoginFragment @Inject constructor() : AbstractLoginFragment() {
|
||||
class LoginFragment @Inject constructor(
|
||||
private val errorFormatter: ErrorFormatter
|
||||
) : AbstractLoginFragment() {
|
||||
|
||||
// TODO Move to viewState?
|
||||
private var passwordShown = false
|
||||
|
@ -70,10 +74,10 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
|
|||
authenticateButton.setOnClickListener { authenticate() }
|
||||
}
|
||||
|
||||
// TODO Move to server selection screen
|
||||
private fun openSso() {
|
||||
loginSharedActionViewModel.post(LoginNavigation.OpenSsoLoginFallback)
|
||||
}
|
||||
// // TODO Move to server selection screen
|
||||
// private fun openSso() {
|
||||
// loginSharedActionViewModel.post(LoginNavigation.OpenSsoLoginFallback)
|
||||
// }
|
||||
|
||||
private fun setupPasswordReveal() {
|
||||
passwordShown = false
|
||||
|
@ -106,65 +110,16 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
|
|||
override fun invalidate() = withState(viewModel) { state ->
|
||||
TransitionManager.beginDelayedTransition(login_fragment)
|
||||
|
||||
when (state.asyncHomeServerLoginFlowRequest) {
|
||||
is Incomplete -> {
|
||||
progressBar.isVisible = true
|
||||
touchArea.isVisible = true
|
||||
loginField.isVisible = false
|
||||
passwordContainer.isVisible = false
|
||||
authenticateButton.isVisible = false
|
||||
passwordShown = false
|
||||
renderPasswordField()
|
||||
}
|
||||
is Fail -> {
|
||||
progressBar.isVisible = false
|
||||
touchArea.isVisible = false
|
||||
loginField.isVisible = false
|
||||
passwordContainer.isVisible = false
|
||||
authenticateButton.isVisible = false
|
||||
Toast.makeText(requireActivity(), "Authenticate failure: ${state.asyncHomeServerLoginFlowRequest.error}", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
is Success -> {
|
||||
progressBar.isVisible = false
|
||||
touchArea.isVisible = false
|
||||
|
||||
when (state.asyncHomeServerLoginFlowRequest()) {
|
||||
LoginMode.Password -> {
|
||||
loginField.isVisible = true
|
||||
passwordContainer.isVisible = true
|
||||
authenticateButton.isVisible = true
|
||||
if (loginField.text.isNullOrBlank() && passwordField.text.isNullOrBlank()) {
|
||||
// Jump focus to login
|
||||
loginField.requestFocus()
|
||||
}
|
||||
}
|
||||
LoginMode.Sso -> {
|
||||
loginField.isVisible = false
|
||||
passwordContainer.isVisible = false
|
||||
authenticateButton.isVisible = false
|
||||
}
|
||||
LoginMode.Unsupported -> {
|
||||
loginField.isVisible = false
|
||||
passwordContainer.isVisible = false
|
||||
authenticateButton.isVisible = false
|
||||
Toast.makeText(requireActivity(), "None of the homeserver login mode is supported by RiotX", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (state.asyncLoginAction) {
|
||||
is Loading -> {
|
||||
progressBar.isVisible = true
|
||||
touchArea.isVisible = true
|
||||
|
||||
// Ensure password is hidden
|
||||
passwordShown = false
|
||||
renderPasswordField()
|
||||
}
|
||||
is Fail -> {
|
||||
progressBar.isVisible = false
|
||||
touchArea.isVisible = false
|
||||
Toast.makeText(requireActivity(), "Authenticate failure: ${state.asyncLoginAction.error}", Toast.LENGTH_LONG).show()
|
||||
// TODO Handle error text properly
|
||||
// TODO Reset error when text is changed
|
||||
passwordFieldTil.error = errorFormatter.toHumanReadable(state.asyncLoginAction.error)
|
||||
}
|
||||
// Success is handled by the LoginActivity
|
||||
is Success -> Unit
|
||||
|
|
|
@ -22,7 +22,8 @@ import im.vector.riotx.core.platform.VectorSharedAction
|
|||
sealed class LoginNavigation : VectorSharedAction {
|
||||
object OpenServerSelection : LoginNavigation()
|
||||
object OnServerSelectionDone : LoginNavigation()
|
||||
data class OnLoginFlowRetrieved(val loginMode: LoginMode) : LoginNavigation()
|
||||
data class OnSignModeSelected(val signMode: SignMode) : LoginNavigation()
|
||||
object OpenSsoLoginFallback : LoginNavigation()
|
||||
object GoBack : LoginNavigation()
|
||||
//object OpenSsoLoginFallback : LoginNavigation()
|
||||
data class OnSsoLoginFallbackError(val errorCode: Int, val description: String, val failingUrl: String) : LoginNavigation()
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ package im.vector.riotx.features.login
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import butterknife.OnClick
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.utils.openUrlInExternalBrowser
|
||||
|
@ -73,8 +75,13 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
|
|||
}
|
||||
|
||||
@OnClick(R.id.loginServerSubmit)
|
||||
fun submit() {
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnServerSelectionDone)
|
||||
fun submit() = withState(viewModel) {
|
||||
if (it.serverType == ServerType.MatrixOrg) {
|
||||
// Request login flow here
|
||||
viewModel.handle(LoginAction.UpdateHomeServer(getString(R.string.matrix_org_server_url)))
|
||||
} else {
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnServerSelectionDone)
|
||||
}
|
||||
}
|
||||
|
||||
override fun resetViewModel() {
|
||||
|
@ -83,5 +90,15 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
|
|||
|
||||
override fun invalidate() = withState(viewModel) {
|
||||
updateSelectedChoice(it.serverType)
|
||||
|
||||
when (it.asyncHomeServerLoginFlowRequest) {
|
||||
is Fail -> {
|
||||
// TODO Display error in a dialog?
|
||||
}
|
||||
is Success -> {
|
||||
// The home server url is valid
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnLoginFlowRetrieved(it.asyncHomeServerLoginFlowRequest.invoke()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,9 @@ import android.view.View
|
|||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.core.view.isVisible
|
||||
import butterknife.OnClick
|
||||
import com.airbnb.mvrx.*
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.error.ErrorFormatter
|
||||
|
@ -115,22 +117,13 @@ class LoginServerUrlFormFragment @Inject constructor(
|
|||
}
|
||||
|
||||
when (state.asyncHomeServerLoginFlowRequest) {
|
||||
is Uninitialized -> {
|
||||
progressBar.isVisible = false
|
||||
touchArea.isVisible = false
|
||||
}
|
||||
is Loading -> {
|
||||
progressBar.isVisible = true
|
||||
touchArea.isVisible = true
|
||||
}
|
||||
is Fail -> {
|
||||
progressBar.isVisible = false
|
||||
touchArea.isVisible = false
|
||||
is Fail -> {
|
||||
// TODO Error text is not correct
|
||||
loginServerUrlFormHomeServerUrlTil.error = errorFormatter.toHumanReadable(state.asyncHomeServerLoginFlowRequest.error)
|
||||
}
|
||||
is Success -> {
|
||||
// The home server is valid, the next screen will be opened by the Activity
|
||||
is Success -> {
|
||||
// The home server url is valid
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnLoginFlowRetrieved(state.asyncHomeServerLoginFlowRequest.invoke()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,13 +55,13 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractLoginFr
|
|||
@OnClick(R.id.loginSignupSigninSignUp)
|
||||
fun signUp() {
|
||||
viewModel.handle(LoginAction.UpdateSignMode(SignMode.SignUp))
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected)
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected(SignMode.SignUp))
|
||||
}
|
||||
|
||||
@OnClick(R.id.loginSignupSigninSignIn)
|
||||
fun signIn() {
|
||||
viewModel.handle(LoginAction.UpdateSignMode(SignMode.SignIn))
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected)
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected(SignMode.SignIn))
|
||||
}
|
||||
|
||||
override fun resetViewModel() {
|
||||
|
|
|
@ -30,13 +30,10 @@ import android.webkit.SslErrorHandler
|
|||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.platform.OnBackPressed
|
||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||
import kotlinx.android.synthetic.main.fragment_login_sso_fallback.*
|
||||
import timber.log.Timber
|
||||
import java.net.URLDecoder
|
||||
|
@ -44,14 +41,10 @@ import javax.inject.Inject
|
|||
|
||||
/**
|
||||
* Only login is supported for the moment
|
||||
* TODO Migrate to new flow
|
||||
*/
|
||||
class LoginSsoFallbackFragment @Inject constructor() : VectorBaseFragment(), OnBackPressed {
|
||||
class LoginSsoFallbackFragment @Inject constructor() : AbstractLoginFragment() {
|
||||
|
||||
private lateinit var loginSharedActionViewModel: LoginSharedActionViewModel
|
||||
private val viewModel: LoginViewModel by activityViewModel()
|
||||
|
||||
var homeServerUrl: String = ""
|
||||
private var homeServerUrl: String = ""
|
||||
|
||||
enum class Mode {
|
||||
MODE_LOGIN,
|
||||
|
@ -71,7 +64,6 @@ class LoginSsoFallbackFragment @Inject constructor() : VectorBaseFragment(), OnB
|
|||
login_sso_fallback_toolbar.title = getString(R.string.login)
|
||||
|
||||
setupWebview()
|
||||
loginSharedActionViewModel = activityViewModelProvider.get(LoginSharedActionViewModel::class.java)
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
|
@ -146,7 +138,7 @@ class LoginSsoFallbackFragment @Inject constructor() : VectorBaseFragment(), OnB
|
|||
super.onReceivedError(view, errorCode, description, failingUrl)
|
||||
|
||||
// on error case, close this fragment
|
||||
loginSharedActionViewModel.post(LoginNavigation.GoBack)
|
||||
loginSharedActionViewModel.post(LoginNavigation.OnSsoLoginFallbackError(errorCode, description, failingUrl))
|
||||
}
|
||||
|
||||
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
||||
|
@ -294,12 +286,16 @@ class LoginSsoFallbackFragment @Inject constructor() : VectorBaseFragment(), OnB
|
|||
}
|
||||
}
|
||||
|
||||
override fun resetViewModel() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return if (login_sso_fallback_webview.canGoBack()) {
|
||||
login_sso_fallback_webview.goBack()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,14 +78,14 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
currentTask = null
|
||||
|
||||
when (action) {
|
||||
LoginAction.ResetLogin -> {
|
||||
LoginAction.ResetLogin -> {
|
||||
setState {
|
||||
copy(
|
||||
asyncLoginAction = Uninitialized
|
||||
)
|
||||
}
|
||||
}
|
||||
LoginAction.ResetHomeServerUrl -> {
|
||||
LoginAction.ResetHomeServerUrl -> {
|
||||
setState {
|
||||
copy(
|
||||
asyncHomeServerLoginFlowRequest = Uninitialized
|
||||
|
@ -99,10 +99,11 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
|||
)
|
||||
}
|
||||
}
|
||||
LoginAction.ResetSignMode -> {
|
||||
LoginAction.ResetSignMode -> {
|
||||
setState {
|
||||
copy(
|
||||
signMode = SignMode.Unknown
|
||||
signMode = SignMode.Unknown,
|
||||
asyncHomeServerLoginFlowRequest = Uninitialized
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package im.vector.riotx.features.login
|
||||
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
|
||||
|
@ -25,7 +26,14 @@ data class LoginViewState(
|
|||
val signMode: SignMode = SignMode.Unknown,
|
||||
val asyncLoginAction: Async<Unit> = Uninitialized,
|
||||
val asyncHomeServerLoginFlowRequest: Async<LoginMode> = Uninitialized
|
||||
) : MvRxState
|
||||
) : MvRxState {
|
||||
|
||||
fun isLoading(): Boolean {
|
||||
// TODO Add other async here
|
||||
return asyncLoginAction is Loading
|
||||
|| asyncHomeServerLoginFlowRequest is Loading
|
||||
}
|
||||
}
|
||||
|
||||
enum class LoginMode {
|
||||
Password,
|
||||
|
|
47
vector/src/main/res/layout/activity_login.xml
Normal file
47
vector/src/main/res/layout/activity_login.xml
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/loginFragmentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/loginLoading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="loginProgressBar,loginTouchArea"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<View
|
||||
android:id="@+id/loginTouchArea"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?vctr_waiting_background_color"
|
||||
android:clickable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loginProgressBar"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_margin="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -66,11 +66,13 @@
|
|||
android:layout_marginTop="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/passwordFieldTil"
|
||||
style="@style/VectorTextInputLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/auth_password_placeholder"
|
||||
app:errorEnabled="true">
|
||||
app:errorEnabled="true"
|
||||
app:errorIconDrawable="@null">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/passwordField"
|
||||
|
@ -129,28 +131,5 @@
|
|||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/touchArea"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?vctr_waiting_background_color"
|
||||
android:clickable="true"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
@ -98,28 +98,5 @@
|
|||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/touchArea"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?vctr_waiting_background_color"
|
||||
android:clickable="true"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
@ -52,4 +52,6 @@
|
|||
<string name="login_server_url_form_modular_notice">Enter the address of the Modular Riot or Server you want to use</string>
|
||||
<string name="login_server_url_form_other_notice">Enter the address of a server or a Riot you want to connect to</string>
|
||||
|
||||
<string name="login_sso_error_message">An error occurred when loading the page: %1$s (%2$d)</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Add table
Reference in a new issue