Merge pull request #4656 from vector-im/feature/adm/dynamic-login-flow
Feature based FTUE flows
This commit is contained in:
commit
bb0725b2e2
|
@ -140,7 +140,7 @@ android {
|
||||||
buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\""
|
buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\""
|
||||||
resValue "string", "build_number", "\"${buildNumber}\""
|
resValue "string", "build_number", "\"${buildNumber}\""
|
||||||
|
|
||||||
buildConfigField "im.vector.app.features.VectorFeatures.LoginVersion", "LOGIN_VERSION", "im.vector.app.features.VectorFeatures.LoginVersion.V1"
|
buildConfigField "im.vector.app.features.VectorFeatures.LoginVariant", "LOGIN_VARIANT", "im.vector.app.features.VectorFeatures.LoginVariant.LEGACY"
|
||||||
|
|
||||||
buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping"
|
buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping"
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ class DebugFeaturesStateFactory @Inject constructor(
|
||||||
return FeaturesState(listOf(
|
return FeaturesState(listOf(
|
||||||
createEnumFeature(
|
createEnumFeature(
|
||||||
label = "Login version",
|
label = "Login version",
|
||||||
selection = debugFeatures.loginVersion(),
|
selection = debugFeatures.loginVariant(),
|
||||||
default = defaultFeatures.loginVersion()
|
default = defaultFeatures.loginVariant()
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,8 @@ class DebugVectorFeatures(
|
||||||
|
|
||||||
private val dataStore = context.dataStore
|
private val dataStore = context.dataStore
|
||||||
|
|
||||||
override fun loginVersion(): VectorFeatures.LoginVersion {
|
override fun loginVariant(): VectorFeatures.LoginVariant {
|
||||||
return readPreferences().getEnum<VectorFeatures.LoginVersion>() ?: vectorFeatures.loginVersion()
|
return readPreferences().getEnum<VectorFeatures.LoginVariant>() ?: vectorFeatures.loginVariant()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Enum<T>> hasEnumOverride(type: KClass<T>) = readPreferences().containsEnum(type)
|
fun <T : Enum<T>> hasEnumOverride(type: KClass<T>) = readPreferences().containsEnum(type)
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".features.login2.LoginActivity2"
|
android:name=".features.ftue.FTUEActivity"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.app.core.extensions
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import com.airbnb.mvrx.ActivityViewModelContext
|
||||||
|
import com.airbnb.mvrx.Mavericks
|
||||||
|
import com.airbnb.mvrx.MavericksState
|
||||||
|
import com.airbnb.mvrx.MavericksViewModel
|
||||||
|
import com.airbnb.mvrx.MavericksViewModelProvider
|
||||||
|
|
||||||
|
inline fun <reified VM : MavericksViewModel<S>, reified S : MavericksState> ComponentActivity.lazyViewModel(): Lazy<VM> {
|
||||||
|
return lazy(mode = LazyThreadSafetyMode.NONE) {
|
||||||
|
MavericksViewModelProvider.get(
|
||||||
|
viewModelClass = VM::class.java,
|
||||||
|
stateClass = S::class.java,
|
||||||
|
viewModelContext = ActivityViewModelContext(this, intent.extras?.get(Mavericks.KEY_ARG)),
|
||||||
|
key = VM::class.java.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -105,7 +105,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
||||||
protected val viewModelProvider
|
protected val viewModelProvider
|
||||||
get() = ViewModelProvider(this, viewModelFactory)
|
get() = ViewModelProvider(this, viewModelFactory)
|
||||||
|
|
||||||
protected fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
|
fun <T : VectorViewEvents> VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
|
||||||
viewEvents
|
viewEvents
|
||||||
.stream()
|
.stream()
|
||||||
.onEach {
|
.onEach {
|
||||||
|
|
|
@ -20,11 +20,12 @@ import im.vector.app.BuildConfig
|
||||||
|
|
||||||
interface VectorFeatures {
|
interface VectorFeatures {
|
||||||
|
|
||||||
fun loginVersion(): LoginVersion
|
fun loginVariant(): LoginVariant
|
||||||
|
|
||||||
enum class LoginVersion {
|
enum class LoginVariant {
|
||||||
V1,
|
LEGACY,
|
||||||
V2
|
FTUE,
|
||||||
|
FTUE_WIP
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class NotificationSettingsVersion {
|
enum class NotificationSettingsVersion {
|
||||||
|
@ -34,5 +35,5 @@ interface VectorFeatures {
|
||||||
}
|
}
|
||||||
|
|
||||||
class DefaultVectorFeatures : VectorFeatures {
|
class DefaultVectorFeatures : VectorFeatures {
|
||||||
override fun loginVersion(): VectorFeatures.LoginVersion = BuildConfig.LOGIN_VERSION
|
override fun loginVariant(): VectorFeatures.LoginVariant = BuildConfig.LOGIN_VARIANT
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,367 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.app.features.ftue
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.children
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.fragment.app.FragmentTransaction
|
||||||
|
import com.airbnb.mvrx.withState
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.POP_BACK_STACK_EXCLUSIVE
|
||||||
|
import im.vector.app.core.extensions.addFragment
|
||||||
|
import im.vector.app.core.extensions.addFragmentToBackstack
|
||||||
|
import im.vector.app.core.extensions.exhaustive
|
||||||
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
|
import im.vector.app.databinding.ActivityLoginBinding
|
||||||
|
import im.vector.app.features.home.HomeActivity
|
||||||
|
import im.vector.app.features.login.LoginAction
|
||||||
|
import im.vector.app.features.login.LoginCaptchaFragment
|
||||||
|
import im.vector.app.features.login.LoginCaptchaFragmentArgument
|
||||||
|
import im.vector.app.features.login.LoginConfig
|
||||||
|
import im.vector.app.features.login.LoginFragment
|
||||||
|
import im.vector.app.features.login.LoginGenericTextInputFormFragment
|
||||||
|
import im.vector.app.features.login.LoginGenericTextInputFormFragmentArgument
|
||||||
|
import im.vector.app.features.login.LoginMode
|
||||||
|
import im.vector.app.features.login.LoginResetPasswordFragment
|
||||||
|
import im.vector.app.features.login.LoginResetPasswordMailConfirmationFragment
|
||||||
|
import im.vector.app.features.login.LoginResetPasswordSuccessFragment
|
||||||
|
import im.vector.app.features.login.LoginServerSelectionFragment
|
||||||
|
import im.vector.app.features.login.LoginServerUrlFormFragment
|
||||||
|
import im.vector.app.features.login.LoginSignUpSignInSelectionFragment
|
||||||
|
import im.vector.app.features.login.LoginSplashFragment
|
||||||
|
import im.vector.app.features.login.LoginViewEvents
|
||||||
|
import im.vector.app.features.login.LoginViewModel
|
||||||
|
import im.vector.app.features.login.LoginViewState
|
||||||
|
import im.vector.app.features.login.LoginWaitForEmailFragment
|
||||||
|
import im.vector.app.features.login.LoginWaitForEmailFragmentArgument
|
||||||
|
import im.vector.app.features.login.LoginWebFragment
|
||||||
|
import im.vector.app.features.login.ServerType
|
||||||
|
import im.vector.app.features.login.SignMode
|
||||||
|
import im.vector.app.features.login.TextInputFormFragmentMode
|
||||||
|
import im.vector.app.features.login.isSupported
|
||||||
|
import im.vector.app.features.login.terms.LoginTermsFragment
|
||||||
|
import im.vector.app.features.login.terms.LoginTermsFragmentArgument
|
||||||
|
import im.vector.app.features.login.terms.toLocalizedLoginTerms
|
||||||
|
import org.matrix.android.sdk.api.auth.registration.FlowResult
|
||||||
|
import org.matrix.android.sdk.api.auth.registration.Stage
|
||||||
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
|
|
||||||
|
private const val FRAGMENT_REGISTRATION_STAGE_TAG = "FRAGMENT_REGISTRATION_STAGE_TAG"
|
||||||
|
private const val FRAGMENT_LOGIN_TAG = "FRAGMENT_LOGIN_TAG"
|
||||||
|
|
||||||
|
class DefaultFTUEVariant(
|
||||||
|
private val views: ActivityLoginBinding,
|
||||||
|
private val loginViewModel: LoginViewModel,
|
||||||
|
private val activity: VectorBaseActivity<ActivityLoginBinding>,
|
||||||
|
private val supportFragmentManager: FragmentManager
|
||||||
|
) : FTUEVariant {
|
||||||
|
|
||||||
|
private val enterAnim = R.anim.enter_fade_in
|
||||||
|
private val exitAnim = R.anim.exit_fade_out
|
||||||
|
|
||||||
|
private val popEnterAnim = R.anim.no_anim
|
||||||
|
private val popExitAnim = R.anim.exit_fade_out
|
||||||
|
|
||||||
|
private val topFragment: Fragment?
|
||||||
|
get() = supportFragmentManager.findFragmentById(views.loginFragmentContainer.id)
|
||||||
|
|
||||||
|
private val commonOption: (FragmentTransaction) -> Unit = { ft ->
|
||||||
|
// Find the loginLogo on the current Fragment, this should not return null
|
||||||
|
(topFragment?.view as? ViewGroup)
|
||||||
|
// Find findViewById does not work, I do not know why
|
||||||
|
// findViewById<View?>(R.id.loginLogo)
|
||||||
|
?.children
|
||||||
|
?.firstOrNull { it.id == R.id.loginLogo }
|
||||||
|
?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
|
ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initUiAndData(isFirstCreation: Boolean) {
|
||||||
|
if (isFirstCreation) {
|
||||||
|
addFirstFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
with(activity) {
|
||||||
|
loginViewModel.onEach {
|
||||||
|
updateWithState(it)
|
||||||
|
}
|
||||||
|
loginViewModel.observeViewEvents { handleLoginViewEvents(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get config extra
|
||||||
|
val loginConfig = activity.intent.getParcelableExtra<LoginConfig?>(FTUEActivity.EXTRA_CONFIG)
|
||||||
|
if (isFirstCreation) {
|
||||||
|
loginViewModel.handle(LoginAction.InitWith(loginConfig))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setIsLoading(isLoading: Boolean) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addFirstFragment() {
|
||||||
|
activity.addFragment(views.loginFragmentContainer, LoginSplashFragment::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleLoginViewEvents(loginViewEvents: LoginViewEvents) {
|
||||||
|
when (loginViewEvents) {
|
||||||
|
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
|
||||||
|
onRegistrationStageNotSupported()
|
||||||
|
} else {
|
||||||
|
if (loginViewEvents.isRegistrationStarted) {
|
||||||
|
// Go on with registration flow
|
||||||
|
handleRegistrationNavigation(loginViewEvents.flowResult)
|
||||||
|
} else {
|
||||||
|
// First ask for login and password
|
||||||
|
// I add a tag to indicate that this fragment is a registration stage.
|
||||||
|
// This way it will be automatically popped in when starting the next registration stage
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginFragment::class.java,
|
||||||
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
|
option = commonOption
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is LoginViewEvents.OutdatedHomeserver -> {
|
||||||
|
MaterialAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.login_error_outdated_homeserver_title)
|
||||||
|
.setMessage(R.string.login_error_outdated_homeserver_warning_content)
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
Unit
|
||||||
|
}
|
||||||
|
is LoginViewEvents.OpenServerSelection ->
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginServerSelectionFragment::class.java,
|
||||||
|
option = { ft ->
|
||||||
|
activity.findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
|
// Disable transition of text
|
||||||
|
// findViewById<View?>(R.id.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
|
// No transition here now actually
|
||||||
|
// 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(loginViewEvents)
|
||||||
|
is LoginViewEvents.OnSignModeSelected -> onSignModeSelected(loginViewEvents)
|
||||||
|
is LoginViewEvents.OnLoginFlowRetrieved ->
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginSignUpSignInSelectionFragment::class.java,
|
||||||
|
option = commonOption)
|
||||||
|
is LoginViewEvents.OnWebLoginError -> onWebLoginError(loginViewEvents)
|
||||||
|
is LoginViewEvents.OnForgetPasswordClicked ->
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginResetPasswordFragment::class.java,
|
||||||
|
option = commonOption)
|
||||||
|
is LoginViewEvents.OnResetPasswordSendThreePidDone -> {
|
||||||
|
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginResetPasswordMailConfirmationFragment::class.java,
|
||||||
|
option = commonOption)
|
||||||
|
}
|
||||||
|
is LoginViewEvents.OnResetPasswordMailConfirmationSuccess -> {
|
||||||
|
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
||||||
|
activity.addFragmentToBackstack(views.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 -> {
|
||||||
|
// Pop the enter email Fragment
|
||||||
|
supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginWaitForEmailFragment::class.java,
|
||||||
|
LoginWaitForEmailFragmentArgument(loginViewEvents.email),
|
||||||
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
|
option = commonOption)
|
||||||
|
}
|
||||||
|
is LoginViewEvents.OnSendMsisdnSuccess -> {
|
||||||
|
// Pop the enter Msisdn Fragment
|
||||||
|
supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginGenericTextInputFormFragment::class.java,
|
||||||
|
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, loginViewEvents.msisdn),
|
||||||
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
|
option = commonOption)
|
||||||
|
}
|
||||||
|
is LoginViewEvents.Failure,
|
||||||
|
is LoginViewEvents.Loading ->
|
||||||
|
// This is handled by the Fragments
|
||||||
|
Unit
|
||||||
|
}.exhaustive
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateWithState(loginViewState: LoginViewState) {
|
||||||
|
if (loginViewState.isUserLogged()) {
|
||||||
|
val intent = HomeActivity.newIntent(
|
||||||
|
activity,
|
||||||
|
accountCreation = loginViewState.signMode == SignMode.SignUp
|
||||||
|
)
|
||||||
|
activity.startActivity(intent)
|
||||||
|
activity.finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading
|
||||||
|
views.loginLoading.isVisible = loginViewState.isLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onWebLoginError(onWebLoginError: LoginViewEvents.OnWebLoginError) {
|
||||||
|
// Pop the backstack
|
||||||
|
supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||||
|
|
||||||
|
// And inform the user
|
||||||
|
MaterialAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.dialog_title_error)
|
||||||
|
.setMessage(activity.getString(R.string.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode))
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onServerSelectionDone(loginViewEvents: LoginViewEvents.OnServerSelectionDone) {
|
||||||
|
when (loginViewEvents.serverType) {
|
||||||
|
ServerType.MatrixOrg -> Unit // In this case, we wait for the login flow
|
||||||
|
ServerType.EMS,
|
||||||
|
ServerType.Other -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginServerUrlFormFragment::class.java,
|
||||||
|
option = commonOption)
|
||||||
|
ServerType.Unknown -> Unit /* Should not happen */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onSignModeSelected(loginViewEvents: LoginViewEvents.OnSignModeSelected) = withState(loginViewModel) { state ->
|
||||||
|
// state.signMode could not be ready yet. So use value from the ViewEvent
|
||||||
|
when (loginViewEvents.signMode) {
|
||||||
|
SignMode.Unknown -> error("Sign mode has to be set before calling this method")
|
||||||
|
SignMode.SignUp -> {
|
||||||
|
// This is managed by the LoginViewEvents
|
||||||
|
}
|
||||||
|
SignMode.SignIn -> {
|
||||||
|
// It depends on the LoginMode
|
||||||
|
when (state.loginMode) {
|
||||||
|
LoginMode.Unknown,
|
||||||
|
is LoginMode.Sso -> error("Developer error")
|
||||||
|
is LoginMode.SsoAndPassword,
|
||||||
|
LoginMode.Password -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginFragment::class.java,
|
||||||
|
tag = FRAGMENT_LOGIN_TAG,
|
||||||
|
option = commonOption)
|
||||||
|
LoginMode.Unsupported -> onLoginModeNotSupported(state.loginModeSupportedTypes)
|
||||||
|
}.exhaustive
|
||||||
|
}
|
||||||
|
SignMode.SignInWithMatrixId -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginFragment::class.java,
|
||||||
|
tag = FRAGMENT_LOGIN_TAG,
|
||||||
|
option = commonOption)
|
||||||
|
}.exhaustive
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the SSO redirection here
|
||||||
|
*/
|
||||||
|
override fun onNewIntent(intent: Intent?) {
|
||||||
|
intent?.data
|
||||||
|
?.let { tryOrNull { it.getQueryParameter("loginToken") } }
|
||||||
|
?.let { loginViewModel.handle(LoginAction.LoginWithToken(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onRegistrationStageNotSupported() {
|
||||||
|
MaterialAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.app_name)
|
||||||
|
.setMessage(activity.getString(R.string.login_registration_not_supported))
|
||||||
|
.setPositiveButton(R.string.yes) { _, _ ->
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginWebFragment::class.java,
|
||||||
|
option = commonOption)
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.no, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onLoginModeNotSupported(supportedTypes: List<String>) {
|
||||||
|
MaterialAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.app_name)
|
||||||
|
.setMessage(activity.getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" }))
|
||||||
|
.setPositiveButton(R.string.yes) { _, _ ->
|
||||||
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginWebFragment::class.java,
|
||||||
|
option = commonOption)
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.no, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleRegistrationNavigation(flowResult: FlowResult) {
|
||||||
|
// Complete all mandatory stages first
|
||||||
|
val mandatoryStage = flowResult.missingStages.firstOrNull { it.mandatory }
|
||||||
|
|
||||||
|
if (mandatoryStage != null) {
|
||||||
|
doStage(mandatoryStage)
|
||||||
|
} else {
|
||||||
|
// Consider optional stages
|
||||||
|
val optionalStage = flowResult.missingStages.firstOrNull { !it.mandatory && it !is Stage.Dummy }
|
||||||
|
if (optionalStage == null) {
|
||||||
|
// Should not happen...
|
||||||
|
} else {
|
||||||
|
doStage(optionalStage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doStage(stage: Stage) {
|
||||||
|
// Ensure there is no fragment for registration stage in the backstack
|
||||||
|
supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||||
|
|
||||||
|
when (stage) {
|
||||||
|
is Stage.ReCaptcha -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginCaptchaFragment::class.java,
|
||||||
|
LoginCaptchaFragmentArgument(stage.publicKey),
|
||||||
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
|
option = commonOption)
|
||||||
|
is Stage.Email -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginGenericTextInputFormFragment::class.java,
|
||||||
|
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory),
|
||||||
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
|
option = commonOption)
|
||||||
|
is Stage.Msisdn -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginGenericTextInputFormFragment::class.java,
|
||||||
|
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory),
|
||||||
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
|
option = commonOption)
|
||||||
|
is Stage.Terms -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
|
LoginTermsFragment::class.java,
|
||||||
|
LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))),
|
||||||
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
|
option = commonOption)
|
||||||
|
else -> Unit // Should not happen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.app.features.ftue
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import im.vector.app.core.extensions.lazyViewModel
|
||||||
|
import im.vector.app.core.platform.ToolbarConfigurable
|
||||||
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
|
import im.vector.app.core.platform.lifecycleAwareLazy
|
||||||
|
import im.vector.app.databinding.ActivityLoginBinding
|
||||||
|
import im.vector.app.features.login.LoginConfig
|
||||||
|
import im.vector.app.features.pin.UnlockedActivity
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class FTUEActivity : VectorBaseActivity<ActivityLoginBinding>(), ToolbarConfigurable, UnlockedActivity {
|
||||||
|
|
||||||
|
private val ftueVariant by lifecycleAwareLazy {
|
||||||
|
ftueVariantFactory.create(this, loginViewModel = lazyViewModel(), loginViewModel2 = lazyViewModel())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject lateinit var ftueVariantFactory: FTUEVariantFactory
|
||||||
|
|
||||||
|
override fun getBinding() = ActivityLoginBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
|
override fun getCoordinatorLayout() = views.coordinatorLayout
|
||||||
|
|
||||||
|
override fun configure(toolbar: MaterialToolbar) {
|
||||||
|
configureToolbar(toolbar)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent?) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
ftueVariant.onNewIntent(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initUiAndData() {
|
||||||
|
ftueVariant.initUiAndData(isFirstCreation())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hack for AccountCreatedFragment
|
||||||
|
fun setIsLoading(isLoading: Boolean) {
|
||||||
|
ftueVariant.setIsLoading(isLoading)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val EXTRA_CONFIG = "EXTRA_CONFIG"
|
||||||
|
|
||||||
|
fun newIntent(context: Context, loginConfig: LoginConfig?): Intent {
|
||||||
|
return Intent(context, FTUEActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_CONFIG, loginConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun redirectIntent(context: Context, data: Uri?): Intent {
|
||||||
|
return Intent(context, FTUEActivity::class.java).apply {
|
||||||
|
setData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FTUEVariant {
|
||||||
|
fun onNewIntent(intent: Intent?)
|
||||||
|
fun initUiAndData(isFirstCreation: Boolean)
|
||||||
|
fun setIsLoading(isLoading: Boolean)
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.app.features.ftue
|
||||||
|
|
||||||
|
import im.vector.app.features.VectorFeatures
|
||||||
|
import im.vector.app.features.login.LoginViewModel
|
||||||
|
import im.vector.app.features.login2.LoginViewModel2
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class FTUEVariantFactory @Inject constructor(
|
||||||
|
private val vectorFeatures: VectorFeatures,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun create(activity: FTUEActivity, loginViewModel: Lazy<LoginViewModel>, loginViewModel2: Lazy<LoginViewModel2>) = when (vectorFeatures.loginVariant()) {
|
||||||
|
VectorFeatures.LoginVariant.LEGACY -> error("Legacy is not supported by the FTUE")
|
||||||
|
VectorFeatures.LoginVariant.FTUE -> DefaultFTUEVariant(
|
||||||
|
views = activity.getBinding(),
|
||||||
|
loginViewModel = loginViewModel.value,
|
||||||
|
activity = activity,
|
||||||
|
supportFragmentManager = activity.supportFragmentManager
|
||||||
|
)
|
||||||
|
VectorFeatures.LoginVariant.FTUE_WIP -> FTUEWipVariant(
|
||||||
|
views = activity.getBinding(),
|
||||||
|
loginViewModel = loginViewModel2.value,
|
||||||
|
activity = activity,
|
||||||
|
supportFragmentManager = activity.supportFragmentManager
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2019 New Vector Ltd
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@ -14,11 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.app.features.login2
|
package im.vector.app.features.ftue
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
|
@ -27,17 +25,13 @@ import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.fragment.app.FragmentTransaction
|
import androidx.fragment.app.FragmentTransaction
|
||||||
import com.airbnb.mvrx.viewModel
|
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.POP_BACK_STACK_EXCLUSIVE
|
import im.vector.app.core.extensions.POP_BACK_STACK_EXCLUSIVE
|
||||||
import im.vector.app.core.extensions.addFragment
|
import im.vector.app.core.extensions.addFragment
|
||||||
import im.vector.app.core.extensions.addFragmentToBackstack
|
import im.vector.app.core.extensions.addFragmentToBackstack
|
||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.extensions.resetBackstack
|
import im.vector.app.core.extensions.resetBackstack
|
||||||
import im.vector.app.core.platform.ToolbarConfigurable
|
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.databinding.ActivityLoginBinding
|
import im.vector.app.databinding.ActivityLoginBinding
|
||||||
import im.vector.app.features.home.HomeActivity
|
import im.vector.app.features.home.HomeActivity
|
||||||
|
@ -49,20 +43,41 @@ import im.vector.app.features.login.TextInputFormFragmentMode
|
||||||
import im.vector.app.features.login.isSupported
|
import im.vector.app.features.login.isSupported
|
||||||
import im.vector.app.features.login.terms.LoginTermsFragmentArgument
|
import im.vector.app.features.login.terms.LoginTermsFragmentArgument
|
||||||
import im.vector.app.features.login.terms.toLocalizedLoginTerms
|
import im.vector.app.features.login.terms.toLocalizedLoginTerms
|
||||||
|
import im.vector.app.features.login2.LoginAction2
|
||||||
|
import im.vector.app.features.login2.LoginCaptchaFragment2
|
||||||
|
import im.vector.app.features.login2.LoginFragmentSigninPassword2
|
||||||
|
import im.vector.app.features.login2.LoginFragmentSigninUsername2
|
||||||
|
import im.vector.app.features.login2.LoginFragmentSignupPassword2
|
||||||
|
import im.vector.app.features.login2.LoginFragmentSignupUsername2
|
||||||
|
import im.vector.app.features.login2.LoginFragmentToAny2
|
||||||
|
import im.vector.app.features.login2.LoginGenericTextInputFormFragment2
|
||||||
|
import im.vector.app.features.login2.LoginResetPasswordFragment2
|
||||||
|
import im.vector.app.features.login2.LoginResetPasswordMailConfirmationFragment2
|
||||||
|
import im.vector.app.features.login2.LoginResetPasswordSuccessFragment2
|
||||||
|
import im.vector.app.features.login2.LoginServerSelectionFragment2
|
||||||
|
import im.vector.app.features.login2.LoginServerUrlFormFragment2
|
||||||
|
import im.vector.app.features.login2.LoginSplashSignUpSignInSelectionFragment2
|
||||||
|
import im.vector.app.features.login2.LoginSsoOnlyFragment2
|
||||||
|
import im.vector.app.features.login2.LoginViewEvents2
|
||||||
|
import im.vector.app.features.login2.LoginViewModel2
|
||||||
|
import im.vector.app.features.login2.LoginViewState2
|
||||||
|
import im.vector.app.features.login2.LoginWaitForEmailFragment2
|
||||||
|
import im.vector.app.features.login2.LoginWebFragment2
|
||||||
import im.vector.app.features.login2.created.AccountCreatedFragment
|
import im.vector.app.features.login2.created.AccountCreatedFragment
|
||||||
import im.vector.app.features.login2.terms.LoginTermsFragment2
|
import im.vector.app.features.login2.terms.LoginTermsFragment2
|
||||||
import im.vector.app.features.pin.UnlockedActivity
|
|
||||||
import org.matrix.android.sdk.api.auth.registration.FlowResult
|
import org.matrix.android.sdk.api.auth.registration.FlowResult
|
||||||
import org.matrix.android.sdk.api.auth.registration.Stage
|
import org.matrix.android.sdk.api.auth.registration.Stage
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
|
|
||||||
/**
|
private const val FRAGMENT_REGISTRATION_STAGE_TAG = "FRAGMENT_REGISTRATION_STAGE_TAG"
|
||||||
* The LoginActivity manages the fragment navigation and also display the loading View
|
private const val FRAGMENT_LOGIN_TAG = "FRAGMENT_LOGIN_TAG"
|
||||||
*/
|
|
||||||
@AndroidEntryPoint
|
|
||||||
open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarConfigurable, UnlockedActivity {
|
|
||||||
|
|
||||||
private val loginViewModel: LoginViewModel2 by viewModel()
|
class FTUEWipVariant(
|
||||||
|
private val views: ActivityLoginBinding,
|
||||||
|
private val loginViewModel: LoginViewModel2,
|
||||||
|
private val activity: VectorBaseActivity<ActivityLoginBinding>,
|
||||||
|
private val supportFragmentManager: FragmentManager
|
||||||
|
) : FTUEVariant {
|
||||||
|
|
||||||
private val enterAnim = R.anim.enter_fade_in
|
private val enterAnim = R.anim.enter_fade_in
|
||||||
private val exitAnim = R.anim.exit_fade_out
|
private val exitAnim = R.anim.exit_fade_out
|
||||||
|
@ -76,39 +91,36 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
private val commonOption: (FragmentTransaction) -> Unit = { ft ->
|
private val commonOption: (FragmentTransaction) -> Unit = { ft ->
|
||||||
// Find the loginLogo on the current Fragment, this should not return null
|
// Find the loginLogo on the current Fragment, this should not return null
|
||||||
(topFragment?.view as? ViewGroup)
|
(topFragment?.view as? ViewGroup)
|
||||||
// Find findViewById does not work, I do not know why
|
// Find activity.findViewById does not work, I do not know why
|
||||||
// findViewById<View?>(R.id.loginLogo)
|
// activity.findViewById<View?>(views.loginLogo)
|
||||||
?.children
|
?.children
|
||||||
?.firstOrNull { 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) ?: "") }
|
||||||
ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun getBinding() = ActivityLoginBinding.inflate(layoutInflater)
|
override fun initUiAndData(isFirstCreation: Boolean) {
|
||||||
|
if (isFirstCreation) {
|
||||||
override fun getCoordinatorLayout() = views.coordinatorLayout
|
|
||||||
|
|
||||||
override fun initUiAndData() {
|
|
||||||
if (isFirstCreation()) {
|
|
||||||
addFirstFragment()
|
addFirstFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
loginViewModel.onEach {
|
with(activity) {
|
||||||
updateWithState(it)
|
loginViewModel.onEach {
|
||||||
|
updateWithState(it)
|
||||||
|
}
|
||||||
|
loginViewModel.observeViewEvents { handleLoginViewEvents(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
loginViewModel.observeViewEvents { handleLoginViewEvents(it) }
|
|
||||||
|
|
||||||
// Get config extra
|
// Get config extra
|
||||||
val loginConfig = intent.getParcelableExtra<LoginConfig?>(EXTRA_CONFIG)
|
val loginConfig = activity.intent.getParcelableExtra<LoginConfig?>(FTUEActivity.EXTRA_CONFIG)
|
||||||
if (isFirstCreation()) {
|
if (isFirstCreation) {
|
||||||
// TODO Check this
|
// TODO Check this
|
||||||
loginViewModel.handle(LoginAction2.InitWith(loginConfig))
|
loginViewModel.handle(LoginAction2.InitWith(loginConfig))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun addFirstFragment() {
|
private fun addFirstFragment() {
|
||||||
addFragment(views.loginFragmentContainer, LoginSplashSignUpSignInSelectionFragment2::class.java)
|
activity.addFragment(views.loginFragmentContainer, LoginSplashSignUpSignInSelectionFragment2::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleLoginViewEvents(event: LoginViewEvents2) {
|
private fun handleLoginViewEvents(event: LoginViewEvents2) {
|
||||||
|
@ -127,7 +139,7 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
// First ask for login and password
|
// First ask for login and password
|
||||||
// I add a tag to indicate that this fragment is a registration stage.
|
// I add a tag to indicate that this fragment is a registration stage.
|
||||||
// This way it will be automatically popped in when starting the next registration stage
|
// This way it will be automatically popped in when starting the next registration stage
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginFragment2::class.java,
|
LoginFragment2::class.java,
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
option = commonOption
|
option = commonOption
|
||||||
|
@ -138,7 +150,7 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OutdatedHomeserver -> {
|
is LoginViewEvents2.OutdatedHomeserver -> {
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.login_error_outdated_homeserver_title)
|
.setTitle(R.string.login_error_outdated_homeserver_title)
|
||||||
.setMessage(R.string.login_error_outdated_homeserver_warning_content)
|
.setMessage(R.string.login_error_outdated_homeserver_warning_content)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
@ -146,54 +158,54 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OpenServerSelection ->
|
is LoginViewEvents2.OpenServerSelection ->
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginServerSelectionFragment2::class.java,
|
LoginServerSelectionFragment2::class.java,
|
||||||
option = { ft ->
|
option = { ft ->
|
||||||
findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
activity.findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
// Disable transition of text
|
// Disable transition of text
|
||||||
// findViewById<View?>(R.id.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
// activity.findViewById<View?>(views.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
// No transition here now actually
|
// No transition here now actually
|
||||||
// findViewById<View?>(R.id.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
// activity.findViewById<View?>(views.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
// TODO Disabled because it provokes a flickering
|
// TODO Disabled because it provokes a flickering
|
||||||
// ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
// ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
||||||
})
|
})
|
||||||
is LoginViewEvents2.OpenHomeServerUrlFormScreen -> {
|
is LoginViewEvents2.OpenHomeServerUrlFormScreen -> {
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginServerUrlFormFragment2::class.java,
|
LoginServerUrlFormFragment2::class.java,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OpenSignInEnterIdentifierScreen -> {
|
is LoginViewEvents2.OpenSignInEnterIdentifierScreen -> {
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginFragmentSigninUsername2::class.java,
|
LoginFragmentSigninUsername2::class.java,
|
||||||
option = { ft ->
|
option = { ft ->
|
||||||
findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
activity.findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
// Disable transition of text
|
// Disable transition of text
|
||||||
// findViewById<View?>(R.id.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
// activity.findViewById<View?>(views.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
// No transition here now actually
|
// No transition here now actually
|
||||||
// findViewById<View?>(R.id.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
// activity.findViewById<View?>(views.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||||
// TODO Disabled because it provokes a flickering
|
// TODO Disabled because it provokes a flickering
|
||||||
// ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
// ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OpenSsoOnlyScreen -> {
|
is LoginViewEvents2.OpenSsoOnlyScreen -> {
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginSsoOnlyFragment2::class.java,
|
LoginSsoOnlyFragment2::class.java,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OnWebLoginError -> onWebLoginError(event)
|
is LoginViewEvents2.OnWebLoginError -> onWebLoginError(event)
|
||||||
is LoginViewEvents2.OpenResetPasswordScreen ->
|
is LoginViewEvents2.OpenResetPasswordScreen ->
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginResetPasswordFragment2::class.java,
|
LoginResetPasswordFragment2::class.java,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
is LoginViewEvents2.OnResetPasswordSendThreePidDone -> {
|
is LoginViewEvents2.OnResetPasswordSendThreePidDone -> {
|
||||||
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginResetPasswordMailConfirmationFragment2::class.java,
|
LoginResetPasswordMailConfirmationFragment2::class.java,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OnResetPasswordMailConfirmationSuccess -> {
|
is LoginViewEvents2.OnResetPasswordMailConfirmationSuccess -> {
|
||||||
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginResetPasswordSuccessFragment2::class.java,
|
LoginResetPasswordSuccessFragment2::class.java,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
|
@ -202,37 +214,37 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OnSendEmailSuccess ->
|
is LoginViewEvents2.OnSendEmailSuccess ->
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginWaitForEmailFragment2::class.java,
|
LoginWaitForEmailFragment2::class.java,
|
||||||
LoginWaitForEmailFragmentArgument(event.email),
|
LoginWaitForEmailFragmentArgument(event.email),
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
is LoginViewEvents2.OpenSigninPasswordScreen -> {
|
is LoginViewEvents2.OpenSigninPasswordScreen -> {
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginFragmentSigninPassword2::class.java,
|
LoginFragmentSigninPassword2::class.java,
|
||||||
tag = FRAGMENT_LOGIN_TAG,
|
tag = FRAGMENT_LOGIN_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OpenSignupPasswordScreen -> {
|
is LoginViewEvents2.OpenSignupPasswordScreen -> {
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginFragmentSignupPassword2::class.java,
|
LoginFragmentSignupPassword2::class.java,
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OpenSignUpChooseUsernameScreen -> {
|
is LoginViewEvents2.OpenSignUpChooseUsernameScreen -> {
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginFragmentSignupUsername2::class.java,
|
LoginFragmentSignupUsername2::class.java,
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OpenSignInWithAnythingScreen -> {
|
is LoginViewEvents2.OpenSignInWithAnythingScreen -> {
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginFragmentToAny2::class.java,
|
LoginFragmentToAny2::class.java,
|
||||||
tag = FRAGMENT_LOGIN_TAG,
|
tag = FRAGMENT_LOGIN_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
is LoginViewEvents2.OnSendMsisdnSuccess ->
|
is LoginViewEvents2.OnSendMsisdnSuccess ->
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginGenericTextInputFormFragment2::class.java,
|
LoginGenericTextInputFormFragment2::class.java,
|
||||||
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, event.msisdn),
|
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, event.msisdn),
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
|
@ -250,14 +262,14 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
|
|
||||||
private fun handleCancelRegistration() {
|
private fun handleCancelRegistration() {
|
||||||
// Cleanup the back stack
|
// Cleanup the back stack
|
||||||
resetBackstack()
|
activity.resetBackstack()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleOnSessionCreated(event: LoginViewEvents2.OnSessionCreated) {
|
private fun handleOnSessionCreated(event: LoginViewEvents2.OnSessionCreated) {
|
||||||
if (event.newAccount) {
|
if (event.newAccount) {
|
||||||
// Propose to set avatar and display name
|
// Propose to set avatar and display name
|
||||||
// Back on this Fragment will finish the Activity
|
// Back on this Fragment will finish the Activity
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
AccountCreatedFragment::class.java,
|
AccountCreatedFragment::class.java,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
} else {
|
} else {
|
||||||
|
@ -267,11 +279,11 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
|
|
||||||
private fun terminate(newAccount: Boolean) {
|
private fun terminate(newAccount: Boolean) {
|
||||||
val intent = HomeActivity.newIntent(
|
val intent = HomeActivity.newIntent(
|
||||||
this,
|
activity,
|
||||||
accountCreation = newAccount
|
accountCreation = newAccount
|
||||||
)
|
)
|
||||||
startActivity(intent)
|
activity.startActivity(intent)
|
||||||
finish()
|
activity.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateWithState(LoginViewState2: LoginViewState2) {
|
private fun updateWithState(LoginViewState2: LoginViewState2) {
|
||||||
|
@ -280,7 +292,7 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack for AccountCreatedFragment
|
// Hack for AccountCreatedFragment
|
||||||
fun setIsLoading(isLoading: Boolean) {
|
override fun setIsLoading(isLoading: Boolean) {
|
||||||
views.loginLoading.isVisible = isLoading
|
views.loginLoading.isVisible = isLoading
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,9 +301,9 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||||
|
|
||||||
// And inform the user
|
// And inform the user
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.dialog_title_error)
|
.setTitle(R.string.dialog_title_error)
|
||||||
.setMessage(getString(R.string.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode))
|
.setMessage(activity.getString(R.string.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode))
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
@ -300,19 +312,17 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
* Handle the SSO redirection here
|
* Handle the SSO redirection here
|
||||||
*/
|
*/
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent?) {
|
||||||
super.onNewIntent(intent)
|
|
||||||
|
|
||||||
intent?.data
|
intent?.data
|
||||||
?.let { tryOrNull { it.getQueryParameter("loginToken") } }
|
?.let { tryOrNull { it.getQueryParameter("loginToken") } }
|
||||||
?.let { loginViewModel.handle(LoginAction2.LoginWithToken(it)) }
|
?.let { loginViewModel.handle(LoginAction2.LoginWithToken(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onRegistrationStageNotSupported() {
|
private fun onRegistrationStageNotSupported() {
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.app_name)
|
.setTitle(R.string.app_name)
|
||||||
.setMessage(getString(R.string.login_registration_not_supported))
|
.setMessage(activity.getString(R.string.login_registration_not_supported))
|
||||||
.setPositiveButton(R.string.yes) { _, _ ->
|
.setPositiveButton(R.string.yes) { _, _ ->
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginWebFragment2::class.java,
|
LoginWebFragment2::class.java,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
|
@ -321,11 +331,11 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onLoginModeNotSupported(supportedTypes: List<String>) {
|
private fun onLoginModeNotSupported(supportedTypes: List<String>) {
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.app_name)
|
.setTitle(R.string.app_name)
|
||||||
.setMessage(getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" }))
|
.setMessage(activity.getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" }))
|
||||||
.setPositiveButton(R.string.yes) { _, _ ->
|
.setPositiveButton(R.string.yes) { _, _ ->
|
||||||
addFragmentToBackstack(views.loginFragmentContainer,
|
activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginWebFragment2::class.java,
|
LoginWebFragment2::class.java,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
}
|
}
|
||||||
|
@ -355,53 +365,27 @@ open class LoginActivity2 : VectorBaseActivity<ActivityLoginBinding>(), ToolbarC
|
||||||
supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
||||||
|
|
||||||
when (stage) {
|
when (stage) {
|
||||||
is Stage.ReCaptcha -> addFragmentToBackstack(views.loginFragmentContainer,
|
is Stage.ReCaptcha -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginCaptchaFragment2::class.java,
|
LoginCaptchaFragment2::class.java,
|
||||||
LoginCaptchaFragmentArgument(stage.publicKey),
|
LoginCaptchaFragmentArgument(stage.publicKey),
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
is Stage.Email -> addFragmentToBackstack(views.loginFragmentContainer,
|
is Stage.Email -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginGenericTextInputFormFragment2::class.java,
|
LoginGenericTextInputFormFragment2::class.java,
|
||||||
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory),
|
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory),
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
is Stage.Msisdn -> addFragmentToBackstack(views.loginFragmentContainer,
|
is Stage.Msisdn -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginGenericTextInputFormFragment2::class.java,
|
LoginGenericTextInputFormFragment2::class.java,
|
||||||
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory),
|
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory),
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
is Stage.Terms -> addFragmentToBackstack(views.loginFragmentContainer,
|
is Stage.Terms -> activity.addFragmentToBackstack(views.loginFragmentContainer,
|
||||||
LoginTermsFragment2::class.java,
|
LoginTermsFragment2::class.java,
|
||||||
LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(getString(R.string.resources_language))),
|
LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))),
|
||||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||||
option = commonOption)
|
option = commonOption)
|
||||||
else -> Unit // Should not happen
|
else -> Unit // Should not happen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun configure(toolbar: MaterialToolbar) {
|
|
||||||
configureToolbar(toolbar)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val FRAGMENT_REGISTRATION_STAGE_TAG = "FRAGMENT_REGISTRATION_STAGE_TAG"
|
|
||||||
private const val FRAGMENT_LOGIN_TAG = "FRAGMENT_LOGIN_TAG"
|
|
||||||
|
|
||||||
private const val EXTRA_CONFIG = "EXTRA_CONFIG"
|
|
||||||
|
|
||||||
// Note that the domain can be displayed to the user for confirmation that he trusts it. So use a human readable string
|
|
||||||
const val VECTOR_REDIRECT_URL = "element://connect"
|
|
||||||
|
|
||||||
fun newIntent(context: Context, loginConfig: LoginConfig?): Intent {
|
|
||||||
return Intent(context, LoginActivity2::class.java).apply {
|
|
||||||
putExtra(EXTRA_CONFIG, loginConfig)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun redirectIntent(context: Context, data: Uri?): Intent {
|
|
||||||
return Intent(context, LoginActivity2::class.java).apply {
|
|
||||||
setData(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -88,7 +88,7 @@ abstract class AbstractSSOLoginFragment<VB : ViewBinding> : AbstractLoginFragmen
|
||||||
if (state.loginMode.hasSso() && state.loginMode.ssoIdentityProviders().isNullOrEmpty()) {
|
if (state.loginMode.hasSso() && state.loginMode.ssoIdentityProviders().isNullOrEmpty()) {
|
||||||
// in this case we can prefetch (not other cases for privacy concerns)
|
// in this case we can prefetch (not other cases for privacy concerns)
|
||||||
loginViewModel.getSsoUrl(
|
loginViewModel.getSsoUrl(
|
||||||
redirectUrl = LoginActivity.VECTOR_REDIRECT_URL,
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
deviceId = state.deviceId,
|
deviceId = state.deviceId,
|
||||||
providerId = null
|
providerId = null
|
||||||
)
|
)
|
||||||
|
|
|
@ -356,9 +356,6 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), ToolbarCo
|
||||||
|
|
||||||
private const val EXTRA_CONFIG = "EXTRA_CONFIG"
|
private const val EXTRA_CONFIG = "EXTRA_CONFIG"
|
||||||
|
|
||||||
// Note that the domain can be displayed to the user for confirmation that he trusts it. So use a human readable string
|
|
||||||
const val VECTOR_REDIRECT_URL = "element://connect"
|
|
||||||
|
|
||||||
fun newIntent(context: Context, loginConfig: LoginConfig?): Intent {
|
fun newIntent(context: Context, loginConfig: LoginConfig?): Intent {
|
||||||
return Intent(context, LoginActivity::class.java).apply {
|
return Intent(context, LoginActivity::class.java).apply {
|
||||||
putExtra(EXTRA_CONFIG, loginConfig)
|
putExtra(EXTRA_CONFIG, loginConfig)
|
||||||
|
|
|
@ -200,7 +200,7 @@ class LoginFragment @Inject constructor() : AbstractSSOLoginFragment<FragmentLog
|
||||||
views.loginSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
views.loginSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
||||||
override fun onProviderSelected(id: String?) {
|
override fun onProviderSelected(id: String?) {
|
||||||
loginViewModel.getSsoUrl(
|
loginViewModel.getSsoUrl(
|
||||||
redirectUrl = LoginActivity.VECTOR_REDIRECT_URL,
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
deviceId = state.deviceId,
|
deviceId = state.deviceId,
|
||||||
providerId = id
|
providerId = id
|
||||||
)
|
)
|
||||||
|
|
|
@ -76,7 +76,7 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOLogi
|
||||||
views.loginSignupSigninSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
views.loginSignupSigninSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
||||||
override fun onProviderSelected(id: String?) {
|
override fun onProviderSelected(id: String?) {
|
||||||
loginViewModel.getSsoUrl(
|
loginViewModel.getSsoUrl(
|
||||||
redirectUrl = LoginActivity.VECTOR_REDIRECT_URL,
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
deviceId = state.deviceId,
|
deviceId = state.deviceId,
|
||||||
providerId = id
|
providerId = id
|
||||||
)
|
)
|
||||||
|
@ -109,7 +109,7 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOLogi
|
||||||
private fun submit() = withState(loginViewModel) { state ->
|
private fun submit() = withState(loginViewModel) { state ->
|
||||||
if (state.loginMode is LoginMode.Sso) {
|
if (state.loginMode is LoginMode.Sso) {
|
||||||
loginViewModel.getSsoUrl(
|
loginViewModel.getSsoUrl(
|
||||||
redirectUrl = LoginActivity.VECTOR_REDIRECT_URL,
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
deviceId = state.deviceId,
|
deviceId = state.deviceId,
|
||||||
providerId = null
|
providerId = null
|
||||||
)
|
)
|
||||||
|
|
|
@ -32,4 +32,9 @@ class SSORedirectRouterActivity : AppCompatActivity() {
|
||||||
navigator.loginSSORedirect(this, intent.data)
|
navigator.loginSSORedirect(this, intent.data)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// Note that the domain can be displayed to the user for confirmation that he trusts it. So use a human readable string
|
||||||
|
const val VECTOR_REDIRECT_URL = "element://connect"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import androidx.browser.customtabs.CustomTabsSession
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.core.utils.openUrlInChromeCustomTab
|
import im.vector.app.core.utils.openUrlInChromeCustomTab
|
||||||
|
import im.vector.app.features.login.SSORedirectRouterActivity
|
||||||
import im.vector.app.features.login.hasSso
|
import im.vector.app.features.login.hasSso
|
||||||
import im.vector.app.features.login.ssoIdentityProviders
|
import im.vector.app.features.login.ssoIdentityProviders
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ abstract class AbstractSSOLoginFragment2<VB : ViewBinding> : AbstractLoginFragme
|
||||||
if (state.loginMode.hasSso() && state.loginMode.ssoIdentityProviders().isNullOrEmpty()) {
|
if (state.loginMode.hasSso() && state.loginMode.ssoIdentityProviders().isNullOrEmpty()) {
|
||||||
// in this case we can prefetch (not other cases for privacy concerns)
|
// in this case we can prefetch (not other cases for privacy concerns)
|
||||||
loginViewModel.getSsoUrl(
|
loginViewModel.getSsoUrl(
|
||||||
redirectUrl = LoginActivity2.VECTOR_REDIRECT_URL,
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
deviceId = state.deviceId,
|
deviceId = state.deviceId,
|
||||||
providerId = null
|
providerId = null
|
||||||
)
|
)
|
||||||
|
|
|
@ -30,6 +30,7 @@ import im.vector.app.core.extensions.hideKeyboard
|
||||||
import im.vector.app.core.extensions.toReducedUrl
|
import im.vector.app.core.extensions.toReducedUrl
|
||||||
import im.vector.app.databinding.FragmentLoginSignupUsername2Binding
|
import im.vector.app.databinding.FragmentLoginSignupUsername2Binding
|
||||||
import im.vector.app.features.login.LoginMode
|
import im.vector.app.features.login.LoginMode
|
||||||
|
import im.vector.app.features.login.SSORedirectRouterActivity
|
||||||
import im.vector.app.features.login.SocialLoginButtonsView
|
import im.vector.app.features.login.SocialLoginButtonsView
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
@ -97,7 +98,7 @@ class LoginFragmentSignupUsername2 @Inject constructor() : AbstractSSOLoginFragm
|
||||||
views.loginSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
views.loginSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
||||||
override fun onProviderSelected(id: String?) {
|
override fun onProviderSelected(id: String?) {
|
||||||
loginViewModel.getSsoUrl(
|
loginViewModel.getSsoUrl(
|
||||||
redirectUrl = LoginActivity2.VECTOR_REDIRECT_URL,
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
deviceId = state.deviceId,
|
deviceId = state.deviceId,
|
||||||
providerId = id
|
providerId = id
|
||||||
)
|
)
|
||||||
|
|
|
@ -31,6 +31,7 @@ import im.vector.app.core.extensions.hidePassword
|
||||||
import im.vector.app.core.extensions.toReducedUrl
|
import im.vector.app.core.extensions.toReducedUrl
|
||||||
import im.vector.app.databinding.FragmentLoginSigninToAny2Binding
|
import im.vector.app.databinding.FragmentLoginSigninToAny2Binding
|
||||||
import im.vector.app.features.login.LoginMode
|
import im.vector.app.features.login.LoginMode
|
||||||
|
import im.vector.app.features.login.SSORedirectRouterActivity
|
||||||
import im.vector.app.features.login.SocialLoginButtonsView
|
import im.vector.app.features.login.SocialLoginButtonsView
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
@ -124,7 +125,7 @@ class LoginFragmentToAny2 @Inject constructor() : AbstractSSOLoginFragment2<Frag
|
||||||
views.loginSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
views.loginSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener {
|
||||||
override fun onProviderSelected(id: String?) {
|
override fun onProviderSelected(id: String?) {
|
||||||
loginViewModel.getSsoUrl(
|
loginViewModel.getSsoUrl(
|
||||||
redirectUrl = LoginActivity2.VECTOR_REDIRECT_URL,
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
deviceId = state.deviceId,
|
deviceId = state.deviceId,
|
||||||
providerId = id
|
providerId = id
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.toReducedUrl
|
import im.vector.app.core.extensions.toReducedUrl
|
||||||
import im.vector.app.databinding.FragmentLoginSsoOnly2Binding
|
import im.vector.app.databinding.FragmentLoginSsoOnly2Binding
|
||||||
|
import im.vector.app.features.login.SSORedirectRouterActivity
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +52,7 @@ class LoginSsoOnlyFragment2 @Inject constructor() : AbstractSSOLoginFragment2<Fr
|
||||||
|
|
||||||
private fun submit() = withState(loginViewModel) { state ->
|
private fun submit() = withState(loginViewModel) { state ->
|
||||||
loginViewModel.getSsoUrl(
|
loginViewModel.getSsoUrl(
|
||||||
redirectUrl = LoginActivity2.VECTOR_REDIRECT_URL,
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
deviceId = state.deviceId,
|
deviceId = state.deviceId,
|
||||||
providerId = null
|
providerId = null
|
||||||
)
|
)
|
||||||
|
|
|
@ -34,11 +34,11 @@ import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.databinding.DialogBaseEditTextBinding
|
import im.vector.app.databinding.DialogBaseEditTextBinding
|
||||||
import im.vector.app.databinding.FragmentLoginAccountCreatedBinding
|
import im.vector.app.databinding.FragmentLoginAccountCreatedBinding
|
||||||
import im.vector.app.features.displayname.getBestName
|
import im.vector.app.features.displayname.getBestName
|
||||||
|
import im.vector.app.features.ftue.FTUEActivity
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
|
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
|
||||||
import im.vector.app.features.login2.AbstractLoginFragment2
|
import im.vector.app.features.login2.AbstractLoginFragment2
|
||||||
import im.vector.app.features.login2.LoginAction2
|
import im.vector.app.features.login2.LoginAction2
|
||||||
import im.vector.app.features.login2.LoginActivity2
|
|
||||||
import im.vector.app.features.login2.LoginViewState2
|
import im.vector.app.features.login2.LoginViewState2
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
@ -130,7 +130,7 @@ class AccountCreatedFragment @Inject constructor(
|
||||||
|
|
||||||
private fun invalidateState(state: AccountCreatedViewState) {
|
private fun invalidateState(state: AccountCreatedViewState) {
|
||||||
// Ugly hack...
|
// Ugly hack...
|
||||||
(activity as? LoginActivity2)?.setIsLoading(state.isLoading)
|
(activity as? FTUEActivity)?.setIsLoading(state.isLoading)
|
||||||
|
|
||||||
views.loginAccountCreatedSubtitle.text = getString(R.string.login_account_created_subtitle, state.userId)
|
views.loginAccountCreatedSubtitle.text = getString(R.string.login_account_created_subtitle, state.userId)
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ import im.vector.app.features.crypto.verification.SupportedVerificationMethodsPr
|
||||||
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
||||||
import im.vector.app.features.debug.DebugMenuActivity
|
import im.vector.app.features.debug.DebugMenuActivity
|
||||||
import im.vector.app.features.devtools.RoomDevToolActivity
|
import im.vector.app.features.devtools.RoomDevToolActivity
|
||||||
|
import im.vector.app.features.ftue.FTUEActivity
|
||||||
import im.vector.app.features.home.room.detail.RoomDetailActivity
|
import im.vector.app.features.home.room.detail.RoomDetailActivity
|
||||||
import im.vector.app.features.home.room.detail.RoomDetailArgs
|
import im.vector.app.features.home.room.detail.RoomDetailArgs
|
||||||
import im.vector.app.features.home.room.detail.search.SearchActivity
|
import im.vector.app.features.home.room.detail.search.SearchActivity
|
||||||
|
@ -59,7 +60,6 @@ import im.vector.app.features.home.room.filtered.FilteredRoomsActivity
|
||||||
import im.vector.app.features.invite.InviteUsersToRoomActivity
|
import im.vector.app.features.invite.InviteUsersToRoomActivity
|
||||||
import im.vector.app.features.login.LoginActivity
|
import im.vector.app.features.login.LoginActivity
|
||||||
import im.vector.app.features.login.LoginConfig
|
import im.vector.app.features.login.LoginConfig
|
||||||
import im.vector.app.features.login2.LoginActivity2
|
|
||||||
import im.vector.app.features.matrixto.MatrixToBottomSheet
|
import im.vector.app.features.matrixto.MatrixToBottomSheet
|
||||||
import im.vector.app.features.media.AttachmentData
|
import im.vector.app.features.media.AttachmentData
|
||||||
import im.vector.app.features.media.BigImageViewerActivity
|
import im.vector.app.features.media.BigImageViewerActivity
|
||||||
|
@ -81,7 +81,6 @@ import im.vector.app.features.settings.VectorPreferences
|
||||||
import im.vector.app.features.settings.VectorSettingsActivity
|
import im.vector.app.features.settings.VectorSettingsActivity
|
||||||
import im.vector.app.features.share.SharedData
|
import im.vector.app.features.share.SharedData
|
||||||
import im.vector.app.features.signout.soft.SoftLogoutActivity
|
import im.vector.app.features.signout.soft.SoftLogoutActivity
|
||||||
import im.vector.app.features.signout.soft.SoftLogoutActivity2
|
|
||||||
import im.vector.app.features.spaces.InviteRoomSpaceChooserBottomSheet
|
import im.vector.app.features.spaces.InviteRoomSpaceChooserBottomSheet
|
||||||
import im.vector.app.features.spaces.SpaceExploreActivity
|
import im.vector.app.features.spaces.SpaceExploreActivity
|
||||||
import im.vector.app.features.spaces.SpacePreviewActivity
|
import im.vector.app.features.spaces.SpacePreviewActivity
|
||||||
|
@ -112,27 +111,26 @@ class DefaultNavigator @Inject constructor(
|
||||||
) : Navigator {
|
) : Navigator {
|
||||||
|
|
||||||
override fun openLogin(context: Context, loginConfig: LoginConfig?, flags: Int) {
|
override fun openLogin(context: Context, loginConfig: LoginConfig?, flags: Int) {
|
||||||
val intent = when (features.loginVersion()) {
|
val intent = when (features.loginVariant()) {
|
||||||
VectorFeatures.LoginVersion.V1 -> LoginActivity.newIntent(context, loginConfig)
|
VectorFeatures.LoginVariant.LEGACY -> LoginActivity.newIntent(context, loginConfig)
|
||||||
VectorFeatures.LoginVersion.V2 -> LoginActivity2.newIntent(context, loginConfig)
|
VectorFeatures.LoginVariant.FTUE,
|
||||||
|
VectorFeatures.LoginVariant.FTUE_WIP -> FTUEActivity.newIntent(context, loginConfig)
|
||||||
}
|
}
|
||||||
intent.addFlags(flags)
|
intent.addFlags(flags)
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loginSSORedirect(context: Context, data: Uri?) {
|
override fun loginSSORedirect(context: Context, data: Uri?) {
|
||||||
val intent = when (features.loginVersion()) {
|
val intent = when (features.loginVariant()) {
|
||||||
VectorFeatures.LoginVersion.V1 -> LoginActivity.redirectIntent(context, data)
|
VectorFeatures.LoginVariant.LEGACY -> LoginActivity.redirectIntent(context, data)
|
||||||
VectorFeatures.LoginVersion.V2 -> LoginActivity2.redirectIntent(context, data)
|
VectorFeatures.LoginVariant.FTUE,
|
||||||
|
VectorFeatures.LoginVariant.FTUE_WIP -> FTUEActivity.redirectIntent(context, data)
|
||||||
}
|
}
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun softLogout(context: Context) {
|
override fun softLogout(context: Context) {
|
||||||
val intent = when (features.loginVersion()) {
|
val intent = SoftLogoutActivity.newIntent(context)
|
||||||
VectorFeatures.LoginVersion.V1 -> SoftLogoutActivity.newIntent(context)
|
|
||||||
VectorFeatures.LoginVersion.V2 -> SoftLogoutActivity2.newIntent(context)
|
|
||||||
}
|
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 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.app.features.signout.soft
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.fragment.app.FragmentManager
|
|
||||||
import com.airbnb.mvrx.Success
|
|
||||||
import com.airbnb.mvrx.viewModel
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import im.vector.app.R
|
|
||||||
import im.vector.app.core.error.ErrorFormatter
|
|
||||||
import im.vector.app.core.extensions.replaceFragment
|
|
||||||
import im.vector.app.features.MainActivity
|
|
||||||
import im.vector.app.features.MainActivityArgs
|
|
||||||
import im.vector.app.features.login2.LoginActivity2
|
|
||||||
import org.matrix.android.sdk.api.failure.GlobalError
|
|
||||||
import org.matrix.android.sdk.api.session.Session
|
|
||||||
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 (nearly) free
|
|
||||||
*
|
|
||||||
* This is just a copy of SoftLogoutActivity2, which extends LoginActivity2
|
|
||||||
*/
|
|
||||||
@AndroidEntryPoint
|
|
||||||
class SoftLogoutActivity2 : LoginActivity2() {
|
|
||||||
|
|
||||||
private val softLogoutViewModel: SoftLogoutViewModel by viewModel()
|
|
||||||
|
|
||||||
@Inject lateinit var session: Session
|
|
||||||
@Inject lateinit var errorFormatter: ErrorFormatter
|
|
||||||
|
|
||||||
override fun initUiAndData() {
|
|
||||||
super.initUiAndData()
|
|
||||||
|
|
||||||
softLogoutViewModel.onEach {
|
|
||||||
updateWithState(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
softLogoutViewModel.observeViewEvents { handleSoftLogoutViewEvents(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleSoftLogoutViewEvents(softLogoutViewEvents: SoftLogoutViewEvents) {
|
|
||||||
when (softLogoutViewEvents) {
|
|
||||||
is SoftLogoutViewEvents.Failure ->
|
|
||||||
showError(errorFormatter.toHumanReadable(softLogoutViewEvents.throwable))
|
|
||||||
is SoftLogoutViewEvents.ErrorNotSameUser -> {
|
|
||||||
// Pop the backstack
|
|
||||||
supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
|
||||||
|
|
||||||
// And inform the user
|
|
||||||
showError(getString(
|
|
||||||
R.string.soft_logout_sso_not_same_user_error,
|
|
||||||
softLogoutViewEvents.currentUserId,
|
|
||||||
softLogoutViewEvents.newUserId)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is SoftLogoutViewEvents.ClearData -> {
|
|
||||||
MainActivity.restartApp(this, MainActivityArgs(clearCredentials = true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showError(message: String) {
|
|
||||||
MaterialAlertDialogBuilder(this)
|
|
||||||
.setTitle(R.string.dialog_title_error)
|
|
||||||
.setMessage(message)
|
|
||||||
.setPositiveButton(R.string.ok, null)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addFirstFragment() {
|
|
||||||
replaceFragment(views.loginFragmentContainer, SoftLogoutFragment::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateWithState(softLogoutViewState: SoftLogoutViewState) {
|
|
||||||
if (softLogoutViewState.asyncLoginAction is Success) {
|
|
||||||
MainActivity.restartApp(this, MainActivityArgs())
|
|
||||||
}
|
|
||||||
|
|
||||||
views.loginLoading.isVisible = softLogoutViewState.isLoading()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun newIntent(context: Context): Intent {
|
|
||||||
return Intent(context, SoftLogoutActivity2::class.java)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleInvalidToken(globalError: GlobalError.InvalidToken) {
|
|
||||||
// No op here
|
|
||||||
Timber.w("Ignoring invalid token global error")
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue