SoftLogout: Inherit from Login stuff to get free forgot password functionality

This commit is contained in:
Benoit Marty 2019-12-13 00:08:21 +01:00
parent 17bcd680b0
commit 14562f7285
6 changed files with 47 additions and 39 deletions

View file

@ -20,6 +20,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
@ -49,13 +50,14 @@ import javax.inject.Inject
/** /**
* The LoginActivity manages the fragment navigation and also display the loading View * The LoginActivity manages the fragment navigation and also display the loading View
*/ */
class LoginActivity : VectorBaseActivity(), ToolbarConfigurable { open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
private val loginViewModel: LoginViewModel by viewModel() private val loginViewModel: LoginViewModel by viewModel()
private lateinit var loginSharedActionViewModel: LoginSharedActionViewModel private lateinit var loginSharedActionViewModel: LoginSharedActionViewModel
@Inject lateinit var loginViewModelFactory: LoginViewModel.Factory @Inject lateinit var loginViewModelFactory: LoginViewModel.Factory
@CallSuper
override fun injectWith(injector: ScreenComponent) { override fun injectWith(injector: ScreenComponent) {
injector.inject(this) injector.inject(this)
} }
@ -75,17 +77,17 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
// Find findViewById does not work, I do not know why // Find findViewById does not work, I do not know why
// findViewById<View?>(R.id.loginLogo) // findViewById<View?>(R.id.loginLogo)
?.children ?.children
?.first { it.id == R.id.loginLogo } ?.firstOrNull { it.id == R.id.loginLogo }
?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") } ?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
// TODO // TODO
ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim) ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
} }
override fun getLayoutRes() = R.layout.activity_login final override fun getLayoutRes() = R.layout.activity_login
override fun initUiAndData() { override fun initUiAndData() {
if (isFirstCreation()) { if (isFirstCreation()) {
addFragment(R.id.loginFragmentContainer, LoginSplashFragment::class.java) addFirstFragment()
} }
// Get config extra // Get config extra
@ -116,6 +118,10 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
.disposeOnDestroy() .disposeOnDestroy()
} }
protected open fun addFirstFragment() {
addFragment(R.id.loginFragmentContainer, LoginSplashFragment::class.java)
}
private fun handleLoginNavigation(loginNavigation: LoginNavigation) { private fun handleLoginNavigation(loginNavigation: LoginNavigation) {
// Assigning to dummy make sure we do not forget a case // Assigning to dummy make sure we do not forget a case
@Suppress("UNUSED_VARIABLE") @Suppress("UNUSED_VARIABLE")

View file

@ -16,6 +16,7 @@
package im.vector.riotx.features.login package im.vector.riotx.features.login
import androidx.fragment.app.FragmentActivity
import com.airbnb.mvrx.* import com.airbnb.mvrx.*
import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject import com.squareup.inject.assisted.AssistedInject
@ -37,6 +38,7 @@ import im.vector.riotx.core.utils.DataSource
import im.vector.riotx.core.utils.PublishDataSource import im.vector.riotx.core.utils.PublishDataSource
import im.vector.riotx.features.notifications.PushRuleTriggerListener import im.vector.riotx.features.notifications.PushRuleTriggerListener
import im.vector.riotx.features.session.SessionListener import im.vector.riotx.features.session.SessionListener
import im.vector.riotx.features.signout.soft.SoftLogoutActivity
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.CancellationException import java.util.concurrent.CancellationException
@ -60,8 +62,11 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
@JvmStatic @JvmStatic
override fun create(viewModelContext: ViewModelContext, state: LoginViewState): LoginViewModel? { override fun create(viewModelContext: ViewModelContext, state: LoginViewState): LoginViewModel? {
val activity: LoginActivity = (viewModelContext as ActivityViewModelContext).activity() return when (val activity: FragmentActivity = (viewModelContext as ActivityViewModelContext).activity()) {
return activity.loginViewModelFactory.create(state) is LoginActivity -> activity.loginViewModelFactory.create(state)
is SoftLogoutActivity -> activity.loginViewModelFactory.create(state)
else -> error("Invalid Activity")
}
} }
} }
@ -452,7 +457,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
} }
private fun startAuthenticationFlow() { private fun startAuthenticationFlow() {
// No op // Ensure Wizard is ready
loginWizard loginWizard
} }

View file

@ -26,17 +26,18 @@ import im.vector.matrix.android.api.session.Session
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.di.ScreenComponent
import im.vector.riotx.core.extensions.replaceFragment import im.vector.riotx.core.extensions.replaceFragment
import im.vector.riotx.core.platform.VectorBaseActivity
import im.vector.riotx.features.MainActivity import im.vector.riotx.features.MainActivity
import im.vector.riotx.features.MainActivityArgs import im.vector.riotx.features.MainActivityArgs
import im.vector.riotx.features.login.LoginActivity
import kotlinx.android.synthetic.main.activity_login.* import kotlinx.android.synthetic.main.activity_login.*
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
/** /**
* In this screen, the user is viewing a message informing that he has been logged out * In this screen, the user is viewing a message informing that he has been logged out
* Extends LoginActivity to get the login with SSO and forget password functionality for free
*/ */
class SoftLogoutActivity : VectorBaseActivity() { class SoftLogoutActivity : LoginActivity() {
private val softLogoutViewModel: SoftLogoutViewModel by viewModel() private val softLogoutViewModel: SoftLogoutViewModel by viewModel()
// TODO For forgotten pwd // TODO For forgotten pwd
@ -46,24 +47,23 @@ class SoftLogoutActivity : VectorBaseActivity() {
@Inject lateinit var session: Session @Inject lateinit var session: Session
override fun injectWith(injector: ScreenComponent) { override fun injectWith(injector: ScreenComponent) {
super.injectWith(injector)
injector.inject(this) injector.inject(this)
} }
override fun getLayoutRes() = R.layout.activity_login
override fun initUiAndData() { override fun initUiAndData() {
super.initUiAndData() super.initUiAndData()
if (isFirstCreation()) {
replaceFragment(R.id.loginFragmentContainer, SoftLogoutFragment::class.java)
}
softLogoutViewModel softLogoutViewModel
.subscribe(this) { .subscribe(this) {
updateWithState(it) updateWithState(it)
} }
} }
override fun addFirstFragment() {
replaceFragment(R.id.loginFragmentContainer, SoftLogoutFragment::class.java)
}
private fun updateWithState(softLogoutViewState: SoftLogoutViewState) { private fun updateWithState(softLogoutViewState: SoftLogoutViewState) {
if (softLogoutViewState.asyncLoginAction is Success) { if (softLogoutViewState.asyncLoginAction is Success) {
MainActivity.restartApp(this, MainActivityArgs()) MainActivity.restartApp(this, MainActivityArgs())

View file

@ -24,13 +24,14 @@ import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.dialogs.withColoredButton import im.vector.riotx.core.dialogs.withColoredButton
import im.vector.riotx.core.error.ErrorFormatter
import im.vector.riotx.core.extensions.cleanup import im.vector.riotx.core.extensions.cleanup
import im.vector.riotx.core.extensions.configureWith import im.vector.riotx.core.extensions.configureWith
import im.vector.riotx.core.extensions.hideKeyboard import im.vector.riotx.core.extensions.hideKeyboard
import im.vector.riotx.core.platform.VectorBaseFragment
import im.vector.riotx.features.MainActivity import im.vector.riotx.features.MainActivity
import im.vector.riotx.features.MainActivityArgs import im.vector.riotx.features.MainActivityArgs
import im.vector.riotx.features.login.AbstractLoginFragment
import im.vector.riotx.features.login.LoginNavigation
import im.vector.riotx.features.login.LoginViewState
import kotlinx.android.synthetic.main.fragment_generic_recycler.* import kotlinx.android.synthetic.main.fragment_generic_recycler.*
import javax.inject.Inject import javax.inject.Inject
@ -40,9 +41,8 @@ import javax.inject.Inject
* - or to cleanup all the data * - or to cleanup all the data
*/ */
class SoftLogoutFragment @Inject constructor( class SoftLogoutFragment @Inject constructor(
private val errorFormatter: ErrorFormatter,
private val softLogoutController: SoftLogoutController private val softLogoutController: SoftLogoutController
) : VectorBaseFragment(), SoftLogoutController.Listener { ) : AbstractLoginFragment(), SoftLogoutController.Listener {
private val softLogoutViewModel: SoftLogoutViewModel by activityViewModel() private val softLogoutViewModel: SoftLogoutViewModel by activityViewModel()
@ -52,9 +52,6 @@ class SoftLogoutFragment @Inject constructor(
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupRecyclerView() setupRecyclerView()
// TODO setupSubmitButton()
// TODO setupPasswordReveal()
} }
private fun setupRecyclerView() { private fun setupRecyclerView() {
@ -82,7 +79,7 @@ class SoftLogoutFragment @Inject constructor(
} }
override fun ssoSubmit() { override fun ssoSubmit() {
// TODO // TODO loginSharedActionViewModel.post(LoginNavigation.Sso)
} }
override fun clearData() { override fun clearData() {
@ -113,29 +110,28 @@ class SoftLogoutFragment @Inject constructor(
private fun cleanupUi() { private fun cleanupUi() {
recyclerView.hideKeyboard() recyclerView.hideKeyboard()
// TODO softLogoutPasswordFieldTil.error = null
}
private fun setupSubmitButton() {
// softLogoutPasswordField.textChanges()
// .map { it.trim().isNotEmpty() }
// .subscribeBy {
// softLogoutPasswordFieldTil.error = null
// softLogoutSubmit.isEnabled = it
// }
// .disposeOnDestroyView()
} }
override fun forgetPasswordClicked() { override fun forgetPasswordClicked() {
// TODO loginSharedActionViewModel.post(LoginNavigation.OnForgetPasswordClicked)
// loginSharedActionViewModel.post(LoginNavigation.OnForgetPasswordClicked)
} }
override fun revealPasswordClicked() { override fun revealPasswordClicked() {
softLogoutViewModel.handle(SoftLogoutAction.TogglePassword) softLogoutViewModel.handle(SoftLogoutAction.TogglePassword)
} }
override fun invalidate() = withState(softLogoutViewModel) { state -> override fun updateWithState(state: LoginViewState) {
softLogoutController.update(state) super.updateWithState(state)
withState(softLogoutViewModel) { state2 ->
softLogoutController.update(state2)
}
}
override fun onError(throwable: Throwable) {
}
override fun resetViewModel() {
// No op
} }
} }

View file

@ -32,7 +32,7 @@ import im.vector.riotx.core.platform.VectorViewModel
import im.vector.riotx.features.login.LoginMode import im.vector.riotx.features.login.LoginMode
/** /**
* TODO Get login flow to tell if it's SSO or Password, or store this info during sigin? * TODO SSO
* TODO Reset password * TODO Reset password
* TODO Test push: disable the pushers? * TODO Test push: disable the pushers?
*/ */

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@id/loginLogo"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="60dp"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"