diff --git a/library/ui-strings/src/main/res/values-fr/strings.xml b/library/ui-strings/src/main/res/values-fr/strings.xml index 2a6d63dc4a..180d04cfd7 100644 --- a/library/ui-strings/src/main/res/values-fr/strings.xml +++ b/library/ui-strings/src/main/res/values-fr/strings.xml @@ -251,7 +251,7 @@ Nouvel appel vidéo Envoyer des fichiers Prendre une photo ou une vidéo - Je me connecte + Se connecter Valider Nom d’utilisateur et/ou mot de passe incorrect Mot de passe oublié \? @@ -1054,7 +1054,7 @@ S’authentifier sur %1$s Je m’inscris Je me connecte - Continuer avec l’authentification unique + Continuer avec AgentConnect Adresse Element Matrix Services Adresse Hébergement privé pour les organisations diff --git a/library/ui-strings/src/main/res/values-fr/strings_tchap.xml b/library/ui-strings/src/main/res/values-fr/strings_tchap.xml index c00f8ce80d..220d872bce 100644 --- a/library/ui-strings/src/main/res/values-fr/strings_tchap.xml +++ b/library/ui-strings/src/main/res/values-fr/strings_tchap.xml @@ -76,9 +76,11 @@ Nouvel e\u2011mail envoyé - Je n’ai pas\nde compte - J’ai un compte - Adresse email + Se connecter par mot de passe + La messagerie instantanée du secteur public + S’identifier avec \nAgentConnect + ➜ Qu’est-ce que AgentConnect ? + Adresse mail professionnelle Utilisez votre adresse professionnelle Votre mot de passe doit contenir au moins 8 caractères, avec au moins un caractère de chaque type : majuscule, minuscule, chiffre, caractère spécial. Confirmer le mot de passe diff --git a/library/ui-strings/src/main/res/values/strings_tchap.xml b/library/ui-strings/src/main/res/values/strings_tchap.xml index 61eb61a9be..2e4cbe416b 100644 --- a/library/ui-strings/src/main/res/values/strings_tchap.xml +++ b/library/ui-strings/src/main/res/values/strings_tchap.xml @@ -76,9 +76,11 @@ Email sent - I do not have\nan account - I already have\nan account - Email + Login by password + Instant messaging of public sector + Authenticate with \nAgentConnect + ➜ What is AgentConnect ? + Professional email Use your business address Your password must include a lower-case letter, an upper-case letter, a number and a symbol and be at a minimum 8 characters in length. Password confirmation diff --git a/library/ui-styles/src/main/res/drawable/ic_tchap_agentconnect.xml b/library/ui-styles/src/main/res/drawable/ic_tchap_agentconnect.xml new file mode 100644 index 0000000000..e83f6298dd --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/ic_tchap_agentconnect.xml @@ -0,0 +1,10 @@ + + + diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt index 98542d2086..a866ff63b1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt @@ -111,5 +111,15 @@ fun RegistrationFlowResponse.toFlowResult(): FlowResult { fun RegistrationFlowResponse.nextUncompletedStage(flowIndex: Int = 0): String? { val completed = completedStages ?: emptyList() - return flows?.getOrNull(flowIndex)?.stages?.firstOrNull { completed.contains(it).not() } + val flows = flows ?: return null + + // TCHAP return LoginFlowTypes.SSO if SSO type is supported by UIA. + if (flowIndex == 0) { + flows.forEach { + if (!it.stages.isNullOrEmpty() && LoginFlowTypes.SSO !in completed && LoginFlowTypes.SSO in it.stages) { + return LoginFlowTypes.SSO + } + } + } + return flows.getOrNull(flowIndex)?.stages?.firstOrNull { it !in completed } } diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 5a92049444..9b325ff112 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -35,7 +35,7 @@ - + @@ -57,7 +57,7 @@ - @@ -99,7 +99,7 @@ android:name="android.max_aspect" android:value="9.9" /> - + @@ -117,16 +117,16 @@ android:theme="@style/Theme.Vector.Black.Transparent"> - - + + - - + + - - - - + + - + diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index b5e6528274..8feea22dc5 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -204,7 +204,7 @@ class HomeActivityViewModel @AssistedInject constructor( Timber.v("DidAskUserConsent: $didAskUser") if (!didAskUser) { // TCHAP user already consented about analytics in the private policy - //_viewEvents.post(HomeActivityViewEvents.ShowAnalyticsOptIn) +// _viewEvents.post(HomeActivityViewEvents.ShowAnalyticsOptIn) _viewEvents.post(HomeActivityViewEvents.SetAnalyticsOptIn) } else { _viewEvents.post(HomeActivityViewEvents.ShowNotificationDialog) diff --git a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt index 634a537de5..af5887a96a 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt @@ -235,6 +235,7 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA } private fun inferAuthDescription(loginViewState: LoginViewState) = when (loginViewState.signMode) { + SignMode.TchapSignInWithSSO, SignMode.TchapSignUp, SignMode.TchapSignIn -> error("developer error") SignMode.Unknown -> null @@ -271,6 +272,7 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA 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.TchapSignInWithSSO, SignMode.TchapSignUp, SignMode.TchapSignIn -> error("developer error") SignMode.Unknown -> error("Sign mode has to be set before calling this method") diff --git a/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt index 6cb419adab..80cd5f289f 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt @@ -89,6 +89,7 @@ class LoginFragment : private fun setupAutoFill(state: LoginViewState) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { when (state.signMode) { + SignMode.TchapSignInWithSSO, SignMode.TchapSignUp, SignMode.TchapSignIn, SignMode.Unknown -> error("developer error") @@ -106,6 +107,7 @@ class LoginFragment : } private fun ssoMode(state: LoginViewState) = when (state.signMode) { + SignMode.TchapSignInWithSSO, SignMode.TchapSignUp, SignMode.TchapSignIn, SignMode.Unknown -> error("developer error") @@ -161,6 +163,7 @@ class LoginFragment : private fun setupUi(state: LoginViewState) { views.loginFieldTil.hint = getString( when (state.signMode) { + SignMode.TchapSignInWithSSO, SignMode.TchapSignUp, SignMode.TchapSignIn, SignMode.Unknown -> error("developer error") @@ -178,6 +181,7 @@ class LoginFragment : views.loginPasswordNotice.isVisible = true } else { val resId = when (state.signMode) { + SignMode.TchapSignInWithSSO, SignMode.TchapSignUp, SignMode.TchapSignIn, SignMode.Unknown -> error("developer error") @@ -231,6 +235,7 @@ class LoginFragment : views.loginSubmit.text = getString( when (state.signMode) { + SignMode.TchapSignInWithSSO, SignMode.TchapSignUp, SignMode.TchapSignIn, SignMode.Unknown -> error("developer error") diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index 4f5f2bd882..965a05b4df 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -431,6 +431,7 @@ class LoginViewModel @AssistedInject constructor( } when (action.signMode) { + SignMode.TchapSignInWithSSO, SignMode.TchapSignUp, SignMode.TchapSignIn -> error("developer error") SignMode.SignUp -> startRegistrationFlow() @@ -570,6 +571,7 @@ class LoginViewModel @AssistedInject constructor( private fun handleLoginOrRegister(action: LoginAction.LoginOrRegister) = withState { state -> when (state.signMode) { + SignMode.TchapSignInWithSSO, SignMode.TchapSignIn, SignMode.TchapSignUp, SignMode.Unknown -> error("Developer error, invalid sign mode") diff --git a/vector/src/main/java/im/vector/app/features/login/SSORedirectRouterActivity.kt b/vector/src/main/java/im/vector/app/features/login/SSORedirectRouterActivity.kt index 19c549fd45..4704048612 100644 --- a/vector/src/main/java/im/vector/app/features/login/SSORedirectRouterActivity.kt +++ b/vector/src/main/java/im/vector/app/features/login/SSORedirectRouterActivity.kt @@ -35,6 +35,6 @@ class SSORedirectRouterActivity : AppCompatActivity() { 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" + const val VECTOR_REDIRECT_URL = "tchap://connect" } } diff --git a/vector/src/main/java/im/vector/app/features/login/SignMode.kt b/vector/src/main/java/im/vector/app/features/login/SignMode.kt index 3438dbe41e..3f4885f373 100644 --- a/vector/src/main/java/im/vector/app/features/login/SignMode.kt +++ b/vector/src/main/java/im/vector/app/features/login/SignMode.kt @@ -23,6 +23,9 @@ enum class SignMode { // TCHAP Account creation TchapSignUp, + // TCHAP Login with AgentConnect + TchapSignInWithSSO, + Unknown, // Account creation diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt index 6497a84f7c..27b2ce5930 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt @@ -56,6 +56,7 @@ sealed interface OnboardingAction : VectorViewModelAction { data class Registration(val userId: String) : UserNameEnteredAction data class Login(val userId: String) : UserNameEnteredAction } + data class LoginWithSSO(val email: String) : OnboardingAction sealed interface AuthenticateAction : OnboardingAction { data class TchapRegister(val email: String, val password: String, val initialDeviceName: String) : AuthenticateAction data class TchapLogin(val email: String, val password: String, val initialDeviceName: String) : AuthenticateAction diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 7f8bdb7a5b..bd2c9a941d 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -179,6 +179,7 @@ class OnboardingViewModel @AssistedInject constructor( override fun handle(action: OnboardingAction) { when (action) { + is OnboardingAction.LoginWithSSO -> tchap.handleLoginWithSSO(action) is OnboardingAction.SplashAction -> handleSplashAction(action) is OnboardingAction.UpdateUseCase -> handleUpdateUseCase(action) OnboardingAction.ResetUseCase -> resetUseCase() @@ -282,8 +283,11 @@ class OnboardingViewModel @AssistedInject constructor( private fun continueToPageAfterSplash(onboardingFlow: OnboardingFlow) { when (onboardingFlow) { + // TCHAP login with SSO + OnboardingFlow.TchapSignInWithSSO -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.TchapSignInWithSSO)) OnboardingFlow.SignUp -> { handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.TchapSignUp)) + // TCHAP disable homeserver selection // _viewEvents.post( // if (vectorFeatures.isOnboardingUseCaseEnabled()) { // OnboardingViewEvents.OpenUseCaseSelection @@ -483,6 +487,7 @@ class OnboardingViewModel @AssistedInject constructor( private fun handleUpdateSignMode(action: OnboardingAction.UpdateSignMode) { updateSignMode(action.signMode) when (action.signMode) { + SignMode.TchapSignInWithSSO -> _viewEvents.post(OnboardingViewEvents.OnSignModeSelected(SignMode.TchapSignInWithSSO)) SignMode.TchapSignIn -> _viewEvents.post(OnboardingViewEvents.OnSignModeSelected(SignMode.TchapSignIn)) SignMode.TchapSignUp -> _viewEvents.post(OnboardingViewEvents.OnSignModeSelected(SignMode.TchapSignUp)) SignMode.SignUp -> handleRegisterAction(RegisterAction.StartRegistration) @@ -808,6 +813,7 @@ class OnboardingViewModel @AssistedInject constructor( updateServerSelection(config, serverTypeOverride, authResult) if (authResult.selectedHomeserver.preferredLoginMode.supportsSignModeScreen()) { when (awaitState().onboardingFlow) { + OnboardingFlow.TchapSignInWithSSO -> error("developer error") OnboardingFlow.SignIn -> { updateSignMode(SignMode.SignIn) when (vectorFeatures.isOnboardingCombinedLoginEnabled()) { @@ -835,6 +841,7 @@ class OnboardingViewModel @AssistedInject constructor( updateServerSelection(config, serverTypeOverride, authResult) _viewEvents.post(OnboardingViewEvents.OnHomeserverEdited) } + OnboardingFlow.TchapSignInWithSSO, OnboardingFlow.SignIn -> { updateServerSelection(config, serverTypeOverride, authResult) _viewEvents.post(OnboardingViewEvents.OnHomeserverEdited) @@ -1003,6 +1010,10 @@ class OnboardingViewModel @AssistedInject constructor( } } + fun handleLoginWithSSO(action: OnboardingAction.LoginWithSSO) { + startTchapAuthenticationFlow(action.email) {} + } + fun startResetPasswordFlow(email: String, onSuccess: () -> Unit) { startTchapAuthenticationFlow(email) { this@OnboardingViewModel.startResetPasswordFlow(email, onSuccess) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt index 58b28ac4e4..983fb18885 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt @@ -64,6 +64,7 @@ data class OnboardingViewState( ) : MavericksState enum class OnboardingFlow { + TchapSignInWithSSO, SignIn, SignUp, SignInSignUp diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt index 7fa79535af..50c54ccbd0 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt @@ -167,4 +167,8 @@ abstract class AbstractFtueAuthFragment : VectorBaseFragment() { + @Inject lateinit var buildMeta: BuildMeta + private val tchap = Tchap() private var isSignupMode = false @@ -111,7 +116,11 @@ class FtueAuthLoginFragment : views.loginField.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_USERNAME) views.passwordField.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD) } - SignMode.TchapSignIn, + SignMode.TchapSignInWithSSO, + SignMode.TchapSignIn -> { + views.loginField.setAutofillHints(HintConstants.AUTOFILL_HINT_EMAIL_ADDRESS) + views.passwordField.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD) + } SignMode.SignIn, SignMode.SignInWithMatrixId -> { views.loginField.setAutofillHints(HintConstants.AUTOFILL_HINT_USERNAME) @@ -125,6 +134,7 @@ class FtueAuthLoginFragment : SignMode.Unknown -> error("developer error") SignMode.TchapSignUp, SignMode.SignUp -> SocialLoginButtonsView.Mode.MODE_SIGN_UP + SignMode.TchapSignInWithSSO, SignMode.TchapSignIn, SignMode.SignIn, SignMode.SignInWithMatrixId -> SocialLoginButtonsView.Mode.MODE_SIGN_IN @@ -148,7 +158,7 @@ class FtueAuthLoginFragment : views.loginFieldTil.error = getString(CommonStrings.error_forbidden_digits_only_username) error++ } - if (password.isEmpty()) { + if (password.isEmpty() && state.signMode != SignMode.TchapSignInWithSSO) { views.passwordFieldTil.error = getString( if (isSignupMode) { CommonStrings.error_empty_field_choose_password @@ -166,8 +176,12 @@ class FtueAuthLoginFragment : } if (error == 0) { - val initialDeviceName = getString(CommonStrings.login_default_session_public_name) - viewModel.handle(state.signMode.toAuthenticateAction(login, password, initialDeviceName)) + if (state.signMode != SignMode.TchapSignInWithSSO) { + val initialDeviceName = getString(CommonStrings.login_default_session_public_name) + viewModel.handle(state.signMode.toAuthenticateAction(login, password, initialDeviceName)) + } else { + viewModel.handle(OnboardingAction.LoginWithSSO(login)) + } } } } @@ -186,6 +200,7 @@ class FtueAuthLoginFragment : SignMode.SignUp -> CommonStrings.login_signup_username_hint SignMode.SignIn -> CommonStrings.login_signin_username_hint SignMode.TchapSignUp, + SignMode.TchapSignInWithSSO, SignMode.TchapSignIn -> CommonStrings.tchap_connection_email SignMode.SignInWithMatrixId -> CommonStrings.login_signin_matrix_id_hint } @@ -199,12 +214,12 @@ class FtueAuthLoginFragment : views.loginPasswordNotice.isVisible = true } else { val resId = when (state.signMode) { - SignMode.Unknown -> error("developer error") SignMode.TchapSignUp, SignMode.SignUp -> CommonStrings.login_signup_to SignMode.TchapSignIn -> CommonStrings.login_connect_to SignMode.SignIn -> CommonStrings.login_connect_to - SignMode.SignInWithMatrixId -> CommonStrings.login_connect_to + SignMode.TchapSignInWithSSO -> CommonStrings.login_social_signin_with + else -> error("developer error") } when (state.serverType) { @@ -228,14 +243,22 @@ class FtueAuthLoginFragment : ServerType.Unknown -> { // TCHAP Hide views if empty views.loginServerIcon.isVisible = false - views.loginTitle.isVisible = false views.loginNotice.isVisible = false + if (state.signMode == SignMode.TchapSignInWithSSO) { + views.passwordFieldTil.isVisible = false + views.loginTitle.text = getString(resId, "AgentConnect") + views.loginACHelp.isVisible = true + views.loginSubmit.setLeftDrawable(im.vector.lib.ui.styles.R.drawable.ic_tchap_agentconnect) + } else { + views.loginTitle.text = getString(resId, buildMeta.applicationName) + views.loginACHelp.isVisible = false + } } } views.loginPasswordNotice.isVisible = false + views.loginSocialLoginContainer.isVisible = false // TCHAP hide SSO container if (state.selectedHomeserver.preferredLoginMode is LoginMode.SsoAndPassword) { - views.loginSocialLoginContainer.isVisible = true views.loginSocialLoginButtons.render(state.selectedHomeserver.preferredLoginMode, ssoMode(state)) { provider -> viewModel.fetchSsoUrl( redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL, @@ -246,7 +269,6 @@ class FtueAuthLoginFragment : ?.let { openInCustomTab(it) } } } else { - views.loginSocialLoginContainer.isVisible = false views.loginSocialLoginButtons.ssoIdentityProviders = null } } @@ -260,20 +282,23 @@ class FtueAuthLoginFragment : SignMode.Unknown -> error("developer error") SignMode.TchapSignUp, SignMode.SignUp -> CommonStrings.login_signup_submit + SignMode.TchapSignInWithSSO -> CommonStrings.login_signin_sso SignMode.TchapSignIn, SignMode.SignIn, SignMode.SignInWithMatrixId -> CommonStrings.login_signin } ) + + views.loginACHelp.debouncedClicks { openUrlInExternalBrowser(requireContext(), TCHAP_AGENTCONNECT_URL) } } - private fun setupSubmitButton() { + private fun setupSubmitButton() = withState(viewModel) { state -> views.loginSubmit.setOnClickListener { submit() } combine( views.loginField.textChanges().map { it.trim().isNotEmpty() }, views.passwordField.textChanges().map { it.isNotEmpty() } ) { isLoginNotEmpty, isPasswordNotEmpty -> - isLoginNotEmpty && isPasswordNotEmpty + (isLoginNotEmpty && isPasswordNotEmpty) || state.signMode == SignMode.TchapSignInWithSSO } .onEach { views.loginFieldTil.error = null @@ -327,6 +352,7 @@ class FtueAuthLoginFragment : tchap.setupUi(state) setupAutoFill(state) setupButtons(state) + tchap.tryLoginSSO(state) if (state.isLoading) { // Ensure password is hidden @@ -354,5 +380,23 @@ class FtueAuthLoginFragment : views.passwordField.imeOptions = EditorInfo.IME_ACTION_DONE } } + + fun tryLoginSSO(state: OnboardingViewState) { + if (state.signMode != SignMode.TchapSignInWithSSO) return + if (views.loginSocialLoginButtons.ssoIdentityProviders.isNullOrEmpty()) return + if (views.loginField.text.isNullOrEmpty()) return + + views.loginSocialLoginButtons.ssoIdentityProviders?.first().let { + viewModel.fetchSsoUrl( + redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL, + deviceId = state.deviceId, + provider = it, + action = SSOAction.LOGIN + ) + ?.let { url -> openInCustomTab(url) } + + views.loginField.text?.clear() + } + } } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt index d203919cfc..3ee30c6e01 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashFragment.kt @@ -24,6 +24,7 @@ import android.view.ViewGroup import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint import im.vector.app.core.resources.BuildMeta +import im.vector.app.core.utils.openUrlInExternalBrowser import im.vector.app.databinding.FragmentTchapWelcomeBinding import im.vector.app.features.VectorFeatures import im.vector.app.features.onboarding.OnboardingAction @@ -53,13 +54,22 @@ class FtueAuthSplashFragment : } private fun setupViews() { + // TCHAP Login with SSO val isAlreadyHaveAccountEnabled = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled() + views.loginSplashAC.apply { + isVisible = isAlreadyHaveAccountEnabled + debouncedClicks { alreadyHaveAnAccountWithSSO() } + } + views.loginSplashACHelp.apply { + isVisible = isAlreadyHaveAccountEnabled + debouncedClicks { openUrlInExternalBrowser(requireContext(), TCHAP_AGENTCONNECT_URL) } + } views.loginSplashSubmit.apply { setText(if (isAlreadyHaveAccountEnabled) CommonStrings.login_splash_create_account else CommonStrings.login_splash_submit) debouncedClicks { splashSubmit(isAlreadyHaveAccountEnabled) } } views.loginSplashAlreadyHaveAccount.apply { - isVisible = vectorFeatures.isOnboardingAlreadyHaveAccountSplashEnabled() + isVisible = isAlreadyHaveAccountEnabled debouncedClicks { alreadyHaveAnAccount() } } @@ -72,6 +82,11 @@ class FtueAuthSplashFragment : } } + /** TCHAP Login with SSO. */ + private fun alreadyHaveAnAccountWithSSO() { + viewModel.handle(OnboardingAction.SplashAction.OnIAlreadyHaveAnAccount(onboardingFlow = OnboardingFlow.TchapSignInWithSSO)) + } + private fun splashSubmit(isAlreadyHaveAccountEnabled: Boolean) { val getStartedFlow = if (isAlreadyHaveAccountEnabled) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp viewModel.handle(OnboardingAction.SplashAction.OnGetStarted(onboardingFlow = getStartedFlow)) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index 67f8864ac3..6a5cb403c2 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -261,6 +261,7 @@ class FtueAuthVariant( else -> { withState(onboardingViewModel) { state -> when (state.onboardingFlow) { + OnboardingFlow.TchapSignInWithSSO -> error("developer error") OnboardingFlow.SignIn -> onStartCombinedLogin() OnboardingFlow.SignUp -> onStartCombinedRegister() OnboardingFlow.SignInSignUp, @@ -323,6 +324,7 @@ class FtueAuthVariant( // state.signMode could not be ready yet. So use value from the ViewEvent when (onboardingViewEvents.signMode) { SignMode.Unknown -> error("Sign mode has to be set before calling this method") + SignMode.TchapSignInWithSSO -> tchap.handleSignInWithSSO() SignMode.TchapSignUp -> tchap.handleSignUpSelected() SignMode.TchapSignIn -> tchap.handleSignInSelected() SignMode.SignUp -> Unit // This case is processed in handleOnboardingViewEvents @@ -558,5 +560,6 @@ class FtueAuthVariant( private inner class Tchap { fun handleSignInSelected() = openAuthLoginFragmentWithTag(FRAGMENT_LOGIN_TAG) fun handleSignUpSelected() = openAuthLoginFragmentWithTag(FRAGMENT_LOGIN_TAG) + fun handleSignInWithSSO() = openAuthLoginFragmentWithTag(FRAGMENT_LOGIN_TAG) } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt index 7427eb0593..b0c1f59104 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueExtensions.kt @@ -23,6 +23,7 @@ import im.vector.lib.ui.styles.R fun SignMode.toAuthenticateAction(login: String, password: String, initialDeviceName: String): OnboardingAction.AuthenticateAction { return when (this) { + SignMode.TchapSignInWithSSO, SignMode.Unknown -> error("developer error") SignMode.TchapSignUp -> OnboardingAction.AuthenticateAction.TchapRegister(email = login, password, initialDeviceName) SignMode.TchapSignIn -> OnboardingAction.AuthenticateAction.TchapLogin(email = login, password, initialDeviceName) diff --git a/vector/src/main/res/layout/fragment_login.xml b/vector/src/main/res/layout/fragment_login.xml index 60ebf88d1e..9bb7fa04e7 100644 --- a/vector/src/main/res/layout/fragment_login.xml +++ b/vector/src/main/res/layout/fragment_login.xml @@ -119,30 +119,34 @@ - - -