From f74b1e6c2e1d4b2008a8cca6f9b49a201c9ca7fa Mon Sep 17 00:00:00 2001
From: Benoit Marty <benoitm@matrix.org>
Date: Mon, 2 Mar 2020 19:11:52 +0100
Subject: [PATCH] Migrate Login Navigation view model to regular ViewEvents

---
 .../vector/riotx/core/di/ViewModelModule.kt   |   8 +-
 .../features/login/AbstractLoginFragment.kt   |   3 -
 .../riotx/features/login/LoginAction.kt       |   2 +
 .../riotx/features/login/LoginActivity.kt     | 121 ++++++++----------
 .../riotx/features/login/LoginFragment.kt     |   2 +-
 .../LoginGenericTextInputFormFragment.kt      |   4 +-
 .../riotx/features/login/LoginNavigation.kt   |  36 ------
 .../login/LoginResetPasswordFragment.kt       |   2 +-
 ...inResetPasswordMailConfirmationFragment.kt |   2 +-
 .../LoginResetPasswordSuccessFragment.kt      |   2 +-
 .../login/LoginServerSelectionFragment.kt     |   5 +-
 .../login/LoginServerUrlFormFragment.kt       |   2 +-
 .../login/LoginSharedActionViewModel.kt       |  22 ----
 .../LoginSignUpSignInSelectionFragment.kt     |   1 -
 .../features/login/LoginSplashFragment.kt     |   2 +-
 .../riotx/features/login/LoginViewEvents.kt   |  18 ++-
 .../riotx/features/login/LoginViewModel.kt    |  20 ++-
 .../riotx/features/login/LoginWebFragment.kt  |   2 +-
 .../signout/soft/SoftLogoutFragment.kt        |   6 +-
 19 files changed, 102 insertions(+), 158 deletions(-)
 delete mode 100644 vector/src/main/java/im/vector/riotx/features/login/LoginNavigation.kt
 delete mode 100644 vector/src/main/java/im/vector/riotx/features/login/LoginSharedActionViewModel.kt

diff --git a/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt
index e480cf22ca..8046f67668 100644
--- a/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt
+++ b/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt
@@ -30,11 +30,10 @@ import im.vector.riotx.features.home.HomeSharedActionViewModel
 import im.vector.riotx.features.home.room.detail.RoomDetailSharedActionViewModel
 import im.vector.riotx.features.home.room.detail.timeline.action.MessageSharedActionViewModel
 import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
-import im.vector.riotx.features.login.LoginSharedActionViewModel
-import im.vector.riotx.features.userdirectory.UserDirectorySharedActionViewModel
 import im.vector.riotx.features.reactions.EmojiChooserViewModel
 import im.vector.riotx.features.roomdirectory.RoomDirectorySharedActionViewModel
 import im.vector.riotx.features.roomprofile.RoomProfileSharedActionViewModel
+import im.vector.riotx.features.userdirectory.UserDirectorySharedActionViewModel
 import im.vector.riotx.features.workers.signout.SignOutViewModel
 
 @Module
@@ -110,11 +109,6 @@ interface ViewModelModule {
     @ViewModelKey(RoomDirectorySharedActionViewModel::class)
     fun bindRoomDirectorySharedActionViewModel(viewModel: RoomDirectorySharedActionViewModel): ViewModel
 
-    @Binds
-    @IntoMap
-    @ViewModelKey(LoginSharedActionViewModel::class)
-    fun bindLoginSharedActionViewModel(viewModel: LoginSharedActionViewModel): ViewModel
-
     @Binds
     @IntoMap
     @ViewModelKey(RoomDetailSharedActionViewModel::class)
diff --git a/vector/src/main/java/im/vector/riotx/features/login/AbstractLoginFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/AbstractLoginFragment.kt
index 83263d05a2..8fceaad07f 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/AbstractLoginFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/AbstractLoginFragment.kt
@@ -38,7 +38,6 @@ import javax.net.ssl.HttpsURLConnection
 abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed {
 
     protected val loginViewModel: LoginViewModel by activityViewModel()
-    protected lateinit var loginSharedActionViewModel: LoginSharedActionViewModel
 
     private var isResetPasswordStarted = false
 
@@ -57,8 +56,6 @@ abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed {
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
-        loginSharedActionViewModel = activityViewModelProvider.get(LoginSharedActionViewModel::class.java)
-
         loginViewModel.observeViewEvents {
             handleLoginViewEvents(it)
         }
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginAction.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginAction.kt
index 90d6754448..3403760136 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginAction.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginAction.kt
@@ -58,4 +58,6 @@ sealed class LoginAction : VectorViewModelAction {
 
     // For the soft logout case
     data class SetupSsoForSessionRecovery(val homeServerUrl: String, val deviceId: String) : LoginAction()
+
+    data class PostViewEvent(val viewEvent: LoginViewEvents) : LoginAction()
 }
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 cd8c1df46e..96da88f15c 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
@@ -55,7 +55,6 @@ import javax.inject.Inject
 open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
 
     private val loginViewModel: LoginViewModel by viewModel()
-    private lateinit var loginSharedActionViewModel: LoginSharedActionViewModel
 
     @Inject lateinit var loginViewModelFactory: LoginViewModel.Factory
 
@@ -99,14 +98,6 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
             loginViewModel.handle(LoginAction.InitWith(loginConfig))
         }
 
-        loginSharedActionViewModel = viewModelProvider.get(LoginSharedActionViewModel::class.java)
-        loginSharedActionViewModel
-                .observe()
-                .subscribe {
-                    handleLoginNavigation(it)
-                }
-                .disposeOnDestroy()
-
         loginViewModel
                 .subscribe(this) {
                     updateWithState(it)
@@ -125,63 +116,9 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
         addFragment(R.id.loginFragmentContainer, LoginSplashFragment::class.java)
     }
 
-    private fun handleLoginNavigation(loginNavigation: LoginNavigation) {
-        when (loginNavigation) {
-            is LoginNavigation.OpenServerSelection                        ->
-                addFragmentToBackstack(R.id.loginFragmentContainer,
-                        LoginServerSelectionFragment::class.java,
-                        option = { ft ->
-                            findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
-                            findViewById<View?>(R.id.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
-                            findViewById<View?>(R.id.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
-                            // TODO Disabled because it provokes a flickering
-                            // ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
-                        })
-            is LoginNavigation.OnServerSelectionDone                      -> onServerSelectionDone()
-            is LoginNavigation.OnSignModeSelected                         -> onSignModeSelected()
-            is LoginNavigation.OnLoginFlowRetrieved                       ->
-                addFragmentToBackstack(R.id.loginFragmentContainer,
-                        LoginSignUpSignInSelectionFragment::class.java,
-                        option = commonOption)
-            is LoginNavigation.OnWebLoginError                            -> onWebLoginError(loginNavigation)
-            is LoginNavigation.OnForgetPasswordClicked                    ->
-                addFragmentToBackstack(R.id.loginFragmentContainer,
-                        LoginResetPasswordFragment::class.java,
-                        option = commonOption)
-            is LoginNavigation.OnResetPasswordSendThreePidDone            -> {
-                supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
-                addFragmentToBackstack(R.id.loginFragmentContainer,
-                        LoginResetPasswordMailConfirmationFragment::class.java,
-                        option = commonOption)
-            }
-            is LoginNavigation.OnResetPasswordMailConfirmationSuccess     -> {
-                supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
-                addFragmentToBackstack(R.id.loginFragmentContainer,
-                        LoginResetPasswordSuccessFragment::class.java,
-                        option = commonOption)
-            }
-            is LoginNavigation.OnResetPasswordMailConfirmationSuccessDone -> {
-                // Go back to the login fragment
-                supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
-            }
-            is LoginNavigation.OnSendEmailSuccess                         ->
-                addFragmentToBackstack(R.id.loginFragmentContainer,
-                        LoginWaitForEmailFragment::class.java,
-                        LoginWaitForEmailFragmentArgument(loginNavigation.email),
-                        tag = FRAGMENT_REGISTRATION_STAGE_TAG,
-                        option = commonOption)
-            is LoginNavigation.OnSendMsisdnSuccess                        ->
-                addFragmentToBackstack(R.id.loginFragmentContainer,
-                        LoginGenericTextInputFormFragment::class.java,
-                        LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, loginNavigation.msisdn),
-                        tag = FRAGMENT_REGISTRATION_STAGE_TAG,
-                        option = commonOption)
-        }.exhaustive
-    }
-
     private fun handleLoginViewEvents(loginViewEvents: LoginViewEvents) {
         when (loginViewEvents) {
-            is LoginViewEvents.RegistrationFlowResult -> {
+            is LoginViewEvents.RegistrationFlowResult                     -> {
                 // Check that all flows are supported by the application
                 if (loginViewEvents.flowResult.missingStages.any { !it.isSupported() }) {
                     // Display a popup to propose use web fallback
@@ -202,15 +139,65 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
                     }
                 }
             }
-            is LoginViewEvents.OutdatedHomeserver     ->
+            is LoginViewEvents.OutdatedHomeserver                         ->
                 AlertDialog.Builder(this)
                         .setTitle(R.string.login_error_outdated_homeserver_title)
                         .setMessage(R.string.login_error_outdated_homeserver_content)
                         .setPositiveButton(R.string.ok, null)
                         .show()
-            is LoginViewEvents.Failure                ->
+            is LoginViewEvents.Failure                                    ->
                 // This is handled by the Fragments
                 Unit
+            is LoginViewEvents.OpenServerSelection                        ->
+                addFragmentToBackstack(R.id.loginFragmentContainer,
+                        LoginServerSelectionFragment::class.java,
+                        option = { ft ->
+                            findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
+                            findViewById<View?>(R.id.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
+                            findViewById<View?>(R.id.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
+                            // TODO Disabled because it provokes a flickering
+                            // ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
+                        })
+            is LoginViewEvents.OnServerSelectionDone                      -> onServerSelectionDone()
+            is LoginViewEvents.OnSignModeSelected                         -> onSignModeSelected()
+            is LoginViewEvents.OnLoginFlowRetrieved                       ->
+                addFragmentToBackstack(R.id.loginFragmentContainer,
+                        LoginSignUpSignInSelectionFragment::class.java,
+                        option = commonOption)
+            is LoginViewEvents.OnWebLoginError                            -> onWebLoginError(loginViewEvents)
+            is LoginViewEvents.OnForgetPasswordClicked                    ->
+                addFragmentToBackstack(R.id.loginFragmentContainer,
+                        LoginResetPasswordFragment::class.java,
+                        option = commonOption)
+            is LoginViewEvents.OnResetPasswordSendThreePidDone            -> {
+                supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
+                addFragmentToBackstack(R.id.loginFragmentContainer,
+                        LoginResetPasswordMailConfirmationFragment::class.java,
+                        option = commonOption)
+            }
+            is LoginViewEvents.OnResetPasswordMailConfirmationSuccess     -> {
+                supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
+                addFragmentToBackstack(R.id.loginFragmentContainer,
+                        LoginResetPasswordSuccessFragment::class.java,
+                        option = commonOption)
+            }
+            is LoginViewEvents.OnResetPasswordMailConfirmationSuccessDone -> {
+                // Go back to the login fragment
+                supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
+            }
+            is LoginViewEvents.OnSendEmailSuccess                         ->
+                addFragmentToBackstack(R.id.loginFragmentContainer,
+                        LoginWaitForEmailFragment::class.java,
+                        LoginWaitForEmailFragmentArgument(loginViewEvents.email),
+                        tag = FRAGMENT_REGISTRATION_STAGE_TAG,
+                        option = commonOption)
+            is LoginViewEvents.OnSendMsisdnSuccess                        ->
+                addFragmentToBackstack(R.id.loginFragmentContainer,
+                        LoginGenericTextInputFormFragment::class.java,
+                        LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, loginViewEvents.msisdn),
+                        tag = FRAGMENT_REGISTRATION_STAGE_TAG,
+                        option = commonOption)
+
         }
     }
 
@@ -229,7 +216,7 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
         loginLoading.isVisible = loginViewState.isLoading()
     }
 
-    private fun onWebLoginError(onWebLoginError: LoginNavigation.OnWebLoginError) {
+    private fun onWebLoginError(onWebLoginError: LoginViewEvents.OnWebLoginError) {
         // Pop the backstack
         supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
 
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt
index 371f669736..c2bd02b817 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt
@@ -190,7 +190,7 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
 
     @OnClick(R.id.forgetPasswordButton)
     fun forgetPasswordClicked() {
-        loginSharedActionViewModel.post(LoginNavigation.OnForgetPasswordClicked)
+        loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnForgetPasswordClicked))
     }
 
     private fun setupPasswordReveal() {
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
index 3ee1cd6d64..5203e60b26 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginGenericTextInputFormFragment.kt
@@ -217,7 +217,7 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
             TextInputFormFragmentMode.SetEmail      -> {
                 if (throwable.is401()) {
                     // This is normal use case, we go to the mail waiting screen
-                    loginSharedActionViewModel.post(LoginNavigation.OnSendEmailSuccess(loginViewModel.currentThreePid ?: ""))
+                    loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnSendEmailSuccess(loginViewModel.currentThreePid ?: "")))
                 } else {
                     loginGenericTextInputFormTil.error = errorFormatter.toHumanReadable(throwable)
                 }
@@ -225,7 +225,7 @@ class LoginGenericTextInputFormFragment @Inject constructor() : AbstractLoginFra
             TextInputFormFragmentMode.SetMsisdn     -> {
                 if (throwable.is401()) {
                     // This is normal use case, we go to the enter code screen
-                    loginSharedActionViewModel.post(LoginNavigation.OnSendMsisdnSuccess(loginViewModel.currentThreePid ?: ""))
+                    loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnSendMsisdnSuccess(loginViewModel.currentThreePid ?: "")))
                 } else {
                     loginGenericTextInputFormTil.error = errorFormatter.toHumanReadable(throwable)
                 }
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginNavigation.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginNavigation.kt
deleted file mode 100644
index 79c6409a3f..0000000000
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginNavigation.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2019 New Vector Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package im.vector.riotx.features.login
-
-import im.vector.riotx.core.platform.VectorSharedAction
-
-// Supported navigation actions for LoginActivity
-sealed class LoginNavigation : VectorSharedAction {
-    object OpenServerSelection : LoginNavigation()
-    object OnServerSelectionDone : LoginNavigation()
-    object OnLoginFlowRetrieved : LoginNavigation()
-    object OnSignModeSelected : LoginNavigation()
-    object OnForgetPasswordClicked : LoginNavigation()
-    object OnResetPasswordSendThreePidDone : LoginNavigation()
-    object OnResetPasswordMailConfirmationSuccess : LoginNavigation()
-    object OnResetPasswordMailConfirmationSuccessDone : LoginNavigation()
-
-    data class OnSendEmailSuccess(val email: String) : LoginNavigation()
-    data class OnSendMsisdnSuccess(val msisdn: String) : LoginNavigation()
-
-    data class OnWebLoginError(val errorCode: Int, val description: String, val failingUrl: String) : LoginNavigation()
-}
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordFragment.kt
index d3a86ef769..d90cfc77e5 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordFragment.kt
@@ -149,7 +149,7 @@ class LoginResetPasswordFragment @Inject constructor() : AbstractLoginFragment()
                 resetPasswordEmailTil.error = errorFormatter.toHumanReadable(state.asyncResetPassword.error)
             }
             is Success -> {
-                loginSharedActionViewModel.post(LoginNavigation.OnResetPasswordSendThreePidDone)
+                Unit
             }
         }
     }
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordMailConfirmationFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordMailConfirmationFragment.kt
index cace48b7f2..f340fb8f9f 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordMailConfirmationFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordMailConfirmationFragment.kt
@@ -64,7 +64,7 @@ class LoginResetPasswordMailConfirmationFragment @Inject constructor() : Abstrac
                         .show()
             }
             is Success -> {
-                loginSharedActionViewModel.post(LoginNavigation.OnResetPasswordMailConfirmationSuccess)
+                Unit
             }
         }
     }
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordSuccessFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordSuccessFragment.kt
index 4faeef1269..fd3c5e6377 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordSuccessFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginResetPasswordSuccessFragment.kt
@@ -29,7 +29,7 @@ class LoginResetPasswordSuccessFragment @Inject constructor() : AbstractLoginFra
 
     @OnClick(R.id.resetPasswordSuccessSubmit)
     fun submit() {
-        loginSharedActionViewModel.post(LoginNavigation.OnResetPasswordMailConfirmationSuccessDone)
+        loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnResetPasswordMailConfirmationSuccessDone))
     }
 
     override fun resetViewModel() {
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginServerSelectionFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginServerSelectionFragment.kt
index ddd56c314e..0e234d3da8 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginServerSelectionFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginServerSelectionFragment.kt
@@ -95,14 +95,13 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
             // Request login flow here
             loginViewModel.handle(LoginAction.UpdateHomeServer(getString(R.string.matrix_org_server_url)))
         } else {
-            loginSharedActionViewModel.post(LoginNavigation.OnServerSelectionDone)
+            loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnServerSelectionDone))
         }
     }
 
     @OnClick(R.id.loginServerIKnowMyIdSubmit)
     fun loginWithMatrixId() {
         loginViewModel.handle(LoginAction.UpdateSignMode(SignMode.SignInWithMatrixId))
-        loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected)
     }
 
     override fun resetViewModel() {
@@ -114,7 +113,7 @@ class LoginServerSelectionFragment @Inject constructor() : AbstractLoginFragment
 
         if (state.loginMode != LoginMode.Unknown) {
             // LoginFlow for matrix.org has been retrieved
-            loginSharedActionViewModel.post(LoginNavigation.OnLoginFlowRetrieved)
+            loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnLoginFlowRetrieved))
         }
     }
 }
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginServerUrlFormFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginServerUrlFormFragment.kt
index 898ee97656..92dcfcc8aa 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginServerUrlFormFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginServerUrlFormFragment.kt
@@ -126,7 +126,7 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment()
 
         if (state.loginMode != LoginMode.Unknown) {
             // The home server url is valid
-            loginSharedActionViewModel.post(LoginNavigation.OnLoginFlowRetrieved)
+            loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnLoginFlowRetrieved))
         }
     }
 }
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginSharedActionViewModel.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginSharedActionViewModel.kt
deleted file mode 100644
index 625208b682..0000000000
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginSharedActionViewModel.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2019 New Vector Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package im.vector.riotx.features.login
-
-import im.vector.riotx.core.platform.VectorSharedActionViewModel
-import javax.inject.Inject
-
-class LoginSharedActionViewModel @Inject constructor() : VectorSharedActionViewModel<LoginNavigation>()
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginSignUpSignInSelectionFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginSignUpSignInSelectionFragment.kt
index 9f084299b7..f09053c883 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginSignUpSignInSelectionFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginSignUpSignInSelectionFragment.kt
@@ -78,7 +78,6 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractLoginFr
     @OnClick(R.id.loginSignupSigninSignIn)
     fun signIn() {
         loginViewModel.handle(LoginAction.UpdateSignMode(SignMode.SignIn))
-        loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected)
     }
 
     override fun resetViewModel() {
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginSplashFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginSplashFragment.kt
index 53de8c2c43..c860d02fec 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginSplashFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginSplashFragment.kt
@@ -29,7 +29,7 @@ class LoginSplashFragment @Inject constructor() : AbstractLoginFragment() {
 
     @OnClick(R.id.loginSplashSubmit)
     fun getStarted() {
-        loginSharedActionViewModel.post(LoginNavigation.OpenServerSelection)
+        loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OpenServerSelection))
     }
 
     override fun resetViewModel() {
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt
index 25747df3d4..c7c2ee6273 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewEvents.kt
@@ -23,10 +23,26 @@ import im.vector.riotx.core.platform.VectorViewEvents
 /**
  * Transient events for Login
  */
-sealed class LoginViewEvents: VectorViewEvents {
+sealed class LoginViewEvents : VectorViewEvents {
     data class Loading(val message: CharSequence? = null) : LoginViewEvents()
     data class Failure(val throwable: Throwable) : LoginViewEvents()
 
     data class RegistrationFlowResult(val flowResult: FlowResult, val isRegistrationStarted: Boolean) : LoginViewEvents()
     object OutdatedHomeserver : LoginViewEvents()
+
+    // Navigation event
+
+    object OpenServerSelection : LoginViewEvents()
+    object OnServerSelectionDone : LoginViewEvents()
+    object OnLoginFlowRetrieved : LoginViewEvents()
+    object OnSignModeSelected : LoginViewEvents()
+    object OnForgetPasswordClicked : LoginViewEvents()
+    object OnResetPasswordSendThreePidDone : LoginViewEvents()
+    object OnResetPasswordMailConfirmationSuccess : LoginViewEvents()
+    object OnResetPasswordMailConfirmationSuccessDone : LoginViewEvents()
+
+    data class OnSendEmailSuccess(val email: String) : LoginViewEvents()
+    data class OnSendMsisdnSuccess(val msisdn: String) : LoginViewEvents()
+
+    data class OnWebLoginError(val errorCode: Int, val description: String, val failingUrl: String) : LoginViewEvents()
 }
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 05f841269f..47360e7c12 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
@@ -116,7 +116,8 @@ class LoginViewModel @AssistedInject constructor(
             is LoginAction.RegisterAction             -> handleRegisterAction(action)
             is LoginAction.ResetAction                -> handleResetAction(action)
             is LoginAction.SetupSsoForSessionRecovery -> handleSetupSsoForSessionRecovery(action)
-        }
+            is LoginAction.PostViewEvent              -> _viewEvents.post(action.viewEvent)
+        }.exhaustive
     }
 
     private fun handleSetupSsoForSessionRecovery(action: LoginAction.SetupSsoForSessionRecovery) {
@@ -328,11 +329,12 @@ class LoginViewModel @AssistedInject constructor(
             )
         }
 
-        if (action.signMode == SignMode.SignUp) {
-            startRegistrationFlow()
-        } else if (action.signMode == SignMode.SignIn) {
-            startAuthenticationFlow()
-        }
+        when (action.signMode) {
+            SignMode.SignUp             -> startRegistrationFlow()
+            SignMode.SignIn             -> startAuthenticationFlow()
+            SignMode.SignInWithMatrixId -> _viewEvents.post(LoginViewEvents.OnSignModeSelected)
+            SignMode.Unknown            -> Unit
+        }.exhaustive
     }
 
     private fun handleUpdateServerType(action: LoginAction.UpdateServerType) {
@@ -373,6 +375,8 @@ class LoginViewModel @AssistedInject constructor(
                                 resetPasswordEmail = action.email
                         )
                     }
+
+                    _viewEvents.post(LoginViewEvents.OnResetPasswordSendThreePidDone)
                 }
 
                 override fun onFailure(failure: Throwable) {
@@ -413,6 +417,8 @@ class LoginViewModel @AssistedInject constructor(
                                 resetPasswordEmail = null
                         )
                     }
+
+                    _viewEvents.post(LoginViewEvents.OnResetPasswordMailConfirmationSuccess)
                 }
 
                 override fun onFailure(failure: Throwable) {
@@ -548,6 +554,8 @@ class LoginViewModel @AssistedInject constructor(
     private fun startAuthenticationFlow() {
         // Ensure Wizard is ready
         loginWizard
+
+        _viewEvents.post(LoginViewEvents.OnSignModeSelected)
     }
 
     private fun onFlowResponse(flowResult: FlowResult) {
diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginWebFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginWebFragment.kt
index f9b0b98f29..cf3b39ebb0 100644
--- a/vector/src/main/java/im/vector/riotx/features/login/LoginWebFragment.kt
+++ b/vector/src/main/java/im/vector/riotx/features/login/LoginWebFragment.kt
@@ -173,7 +173,7 @@ class LoginWebFragment @Inject constructor(
             override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) {
                 super.onReceivedError(view, errorCode, description, failingUrl)
 
-                loginSharedActionViewModel.post(LoginNavigation.OnWebLoginError(errorCode, description, failingUrl))
+                loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnWebLoginError(errorCode, description, failingUrl)))
             }
 
             override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
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 d3288c5b2e..13b90f26e8 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
@@ -30,7 +30,7 @@ import im.vector.riotx.core.extensions.hideKeyboard
 import im.vector.riotx.features.login.AbstractLoginFragment
 import im.vector.riotx.features.login.LoginAction
 import im.vector.riotx.features.login.LoginMode
-import im.vector.riotx.features.login.LoginNavigation
+import im.vector.riotx.features.login.LoginViewEvents
 import kotlinx.android.synthetic.main.fragment_generic_recycler.*
 import javax.inject.Inject
 
@@ -94,7 +94,7 @@ class SoftLogoutFragment @Inject constructor(
     }
 
     override fun signinFallbackSubmit() {
-        loginSharedActionViewModel.post(LoginNavigation.OnSignModeSelected)
+        loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnSignModeSelected))
     }
 
     override fun clearData() {
@@ -124,7 +124,7 @@ class SoftLogoutFragment @Inject constructor(
     }
 
     override fun forgetPasswordClicked() {
-        loginSharedActionViewModel.post(LoginNavigation.OnForgetPasswordClicked)
+        loginViewModel.handle(LoginAction.PostViewEvent(LoginViewEvents.OnForgetPasswordClicked))
     }
 
     override fun revealPasswordClicked() {