From 14562f72852d67b313aa0814ee0b01820d1bdb9a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 13 Dec 2019 00:08:21 +0100 Subject: [PATCH] SoftLogout: Inherit from Login stuff to get free forgot password functionality --- .../riotx/features/login/LoginActivity.kt | 14 +++++-- .../riotx/features/login/LoginViewModel.kt | 11 +++-- .../signout/soft/SoftLogoutActivity.kt | 16 +++---- .../signout/soft/SoftLogoutFragment.kt | 42 +++++++++---------- .../signout/soft/SoftLogoutViewModel.kt | 2 +- .../src/main/res/layout/item_login_header.xml | 1 + 6 files changed, 47 insertions(+), 39 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt index fd3094d5ae..2efce4d8f7 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/LoginActivity.kt @@ -20,6 +20,7 @@ import android.content.Context import android.content.Intent import android.view.View import android.view.ViewGroup +import androidx.annotation.CallSuper import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.Toolbar 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 */ -class LoginActivity : VectorBaseActivity(), ToolbarConfigurable { +open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable { private val loginViewModel: LoginViewModel by viewModel() private lateinit var loginSharedActionViewModel: LoginSharedActionViewModel @Inject lateinit var loginViewModelFactory: LoginViewModel.Factory + @CallSuper override fun injectWith(injector: ScreenComponent) { injector.inject(this) } @@ -75,17 +77,17 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable { // Find findViewById does not work, I do not know why // findViewById(R.id.loginLogo) ?.children - ?.first { it.id == R.id.loginLogo } + ?.firstOrNull { it.id == R.id.loginLogo } ?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") } // TODO ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim) } - override fun getLayoutRes() = R.layout.activity_login + final override fun getLayoutRes() = R.layout.activity_login override fun initUiAndData() { if (isFirstCreation()) { - addFragment(R.id.loginFragmentContainer, LoginSplashFragment::class.java) + addFirstFragment() } // Get config extra @@ -116,6 +118,10 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable { .disposeOnDestroy() } + protected open fun addFirstFragment() { + addFragment(R.id.loginFragmentContainer, LoginSplashFragment::class.java) + } + private fun handleLoginNavigation(loginNavigation: LoginNavigation) { // Assigning to dummy make sure we do not forget a case @Suppress("UNUSED_VARIABLE") diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt index 00207cbfbf..3972c2cdc6 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt @@ -16,6 +16,7 @@ package im.vector.riotx.features.login +import androidx.fragment.app.FragmentActivity import com.airbnb.mvrx.* import com.squareup.inject.assisted.Assisted 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.features.notifications.PushRuleTriggerListener import im.vector.riotx.features.session.SessionListener +import im.vector.riotx.features.signout.soft.SoftLogoutActivity import timber.log.Timber import java.util.concurrent.CancellationException @@ -60,8 +62,11 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi @JvmStatic override fun create(viewModelContext: ViewModelContext, state: LoginViewState): LoginViewModel? { - val activity: LoginActivity = (viewModelContext as ActivityViewModelContext).activity() - return activity.loginViewModelFactory.create(state) + return when (val activity: FragmentActivity = (viewModelContext as ActivityViewModelContext).activity()) { + 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() { - // No op + // Ensure Wizard is ready loginWizard } diff --git a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutActivity.kt b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutActivity.kt index f7e19af25a..1cd2a7df5e 100644 --- a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutActivity.kt @@ -26,17 +26,18 @@ import im.vector.matrix.android.api.session.Session import im.vector.riotx.R import im.vector.riotx.core.di.ScreenComponent 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.MainActivityArgs +import im.vector.riotx.features.login.LoginActivity import kotlinx.android.synthetic.main.activity_login.* import timber.log.Timber import javax.inject.Inject /** * 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() // TODO For forgotten pwd @@ -46,24 +47,23 @@ class SoftLogoutActivity : VectorBaseActivity() { @Inject lateinit var session: Session override fun injectWith(injector: ScreenComponent) { + super.injectWith(injector) injector.inject(this) } - override fun getLayoutRes() = R.layout.activity_login - override fun initUiAndData() { super.initUiAndData() - if (isFirstCreation()) { - replaceFragment(R.id.loginFragmentContainer, SoftLogoutFragment::class.java) - } - softLogoutViewModel .subscribe(this) { updateWithState(it) } } + override fun addFirstFragment() { + replaceFragment(R.id.loginFragmentContainer, SoftLogoutFragment::class.java) + } + private fun updateWithState(softLogoutViewState: SoftLogoutViewState) { if (softLogoutViewState.asyncLoginAction is Success) { MainActivity.restartApp(this, MainActivityArgs()) diff --git a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt index 3973d841b3..594aef54d2 100644 --- a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt @@ -24,13 +24,14 @@ import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState import im.vector.riotx.R 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.configureWith 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.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 javax.inject.Inject @@ -40,9 +41,8 @@ import javax.inject.Inject * - or to cleanup all the data */ class SoftLogoutFragment @Inject constructor( - private val errorFormatter: ErrorFormatter, private val softLogoutController: SoftLogoutController -) : VectorBaseFragment(), SoftLogoutController.Listener { +) : AbstractLoginFragment(), SoftLogoutController.Listener { private val softLogoutViewModel: SoftLogoutViewModel by activityViewModel() @@ -52,9 +52,6 @@ class SoftLogoutFragment @Inject constructor( super.onViewCreated(view, savedInstanceState) setupRecyclerView() - - // TODO setupSubmitButton() - // TODO setupPasswordReveal() } private fun setupRecyclerView() { @@ -82,7 +79,7 @@ class SoftLogoutFragment @Inject constructor( } override fun ssoSubmit() { - // TODO + // TODO loginSharedActionViewModel.post(LoginNavigation.Sso) } override fun clearData() { @@ -113,29 +110,28 @@ class SoftLogoutFragment @Inject constructor( private fun cleanupUi() { 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() { - // TODO - // loginSharedActionViewModel.post(LoginNavigation.OnForgetPasswordClicked) + loginSharedActionViewModel.post(LoginNavigation.OnForgetPasswordClicked) } override fun revealPasswordClicked() { softLogoutViewModel.handle(SoftLogoutAction.TogglePassword) } - override fun invalidate() = withState(softLogoutViewModel) { state -> - softLogoutController.update(state) + override fun updateWithState(state: LoginViewState) { + super.updateWithState(state) + + withState(softLogoutViewModel) { state2 -> + softLogoutController.update(state2) + } + } + + override fun onError(throwable: Throwable) { + } + + override fun resetViewModel() { + // No op } } diff --git a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewModel.kt b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewModel.kt index a7b15cb02b..944e220aa8 100644 --- a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutViewModel.kt @@ -32,7 +32,7 @@ import im.vector.riotx.core.platform.VectorViewModel 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 Test push: disable the pushers? */ diff --git a/vector/src/main/res/layout/item_login_header.xml b/vector/src/main/res/layout/item_login_header.xml index 1c9c51a2f8..333d15ed81 100644 --- a/vector/src/main/res/layout/item_login_header.xml +++ b/vector/src/main/res/layout/item_login_header.xml @@ -1,5 +1,6 @@