diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index a13db6a6db..1c3daf9c3d 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3385,7 +3385,7 @@
The request was denied on the other device.
Open ${app_name} on your other device
Go to Settings -> Security & Privacy -> Show All Sessions
- Select \'Show QR code\'
+ Select \'Show QR code in this device\'
Start at the sign in screen
Select \'Sign in with QR code\'
Start at the sign in screen
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt
index d65e629b71..2c3cb440b6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt
@@ -20,7 +20,6 @@ import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.wellknown.WellknownResult
-import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.orTrue
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.internal.auth.version.Versions
@@ -144,8 +143,8 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
homeServerCapabilitiesEntity.lastVersionIdentityServerSupported = getVersionResult.isLoginAndRegistrationSupportedBySdk()
homeServerCapabilitiesEntity.canControlLogoutDevices = getVersionResult.doesServerSupportLogoutDevices()
homeServerCapabilitiesEntity.canUseThreading = /* capabilities?.threads?.enabled.orFalse() || */
- getVersionResult.doesServerSupportThreads().orFalse()
- homeServerCapabilitiesEntity.canLoginWithQrCode = getVersionResult.doesServerSupportQrCodeLogin().orFalse()
+ getVersionResult.doesServerSupportThreads()
+ homeServerCapabilitiesEntity.canLoginWithQrCode = getVersionResult.doesServerSupportQrCodeLogin()
}
if (getWellknownResult != null && getWellknownResult is WellknownResult.Prompt) {
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginAction.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginAction.kt
index d946f744cf..8854d0720f 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginAction.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginAction.kt
@@ -20,6 +20,6 @@ import im.vector.app.core.platform.VectorViewModelAction
sealed class QrCodeLoginAction : VectorViewModelAction {
data class OnQrCodeScanned(val qrCode: String) : QrCodeLoginAction()
- object QrCodeViewStarted : QrCodeLoginAction()
+ object GenerateQrCode : QrCodeLoginAction()
object ShowQrCode : QrCodeLoginAction()
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginActivity.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginActivity.kt
index 29190a70cb..f5fd17c0c8 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginActivity.kt
@@ -26,7 +26,6 @@ import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.core.extensions.addFragment
import im.vector.app.core.platform.SimpleFragmentActivity
import im.vector.lib.core.utils.compat.getParcelableCompat
-import org.matrix.android.sdk.api.extensions.orFalse
import timber.log.Timber
@AndroidEntryPoint
@@ -45,7 +44,7 @@ class QrCodeLoginActivity : SimpleFragmentActivity() {
showInstructionsFragment(qrCodeLoginArgs)
}
QrCodeLoginType.LINK_A_DEVICE -> {
- if (qrCodeLoginArgs.showQrCodeByDefault.orFalse()) {
+ if (qrCodeLoginArgs.showQrCodeImmediately) {
handleNavigateToShowQrCodeScreen()
} else {
showInstructionsFragment(qrCodeLoginArgs)
@@ -54,6 +53,7 @@ class QrCodeLoginActivity : SimpleFragmentActivity() {
null -> {
Timber.i("QrCodeLoginArgs is null. This is not expected.")
finish()
+ return
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginArgs.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginArgs.kt
index c7b681c488..6c23d07c0f 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginArgs.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginArgs.kt
@@ -22,5 +22,5 @@ import kotlinx.parcelize.Parcelize
@Parcelize
data class QrCodeLoginArgs(
val loginType: QrCodeLoginType,
- val showQrCodeByDefault: Boolean,
+ val showQrCodeImmediately: Boolean,
) : Parcelable
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginHeaderView.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginHeaderView.kt
index f14d711d3c..03478d2f50 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginHeaderView.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginHeaderView.kt
@@ -24,6 +24,7 @@ import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.res.use
import im.vector.app.R
+import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.databinding.ViewQrCodeLoginHeaderBinding
class QrCodeLoginHeaderView @JvmOverloads constructor(
@@ -52,27 +53,26 @@ class QrCodeLoginHeaderView @JvmOverloads constructor(
private fun setTitle(typedArray: TypedArray) {
val title = typedArray.getString(R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderTitle)
- binding.qrCodeLoginHeaderTitleTextView.text = title
+ setTitle(title)
}
private fun setDescription(typedArray: TypedArray) {
val description = typedArray.getString(R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderDescription)
- binding.qrCodeLoginHeaderDescriptionTextView.text = description
+ setDescription(description)
}
private fun setImage(typedArray: TypedArray) {
val imageResource = typedArray.getResourceId(R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderImageResource, 0)
val backgroundTint = typedArray.getColor(R.styleable.QrCodeLoginHeaderView_qrCodeLoginHeaderImageBackgroundTint, 0)
- binding.qrCodeLoginHeaderImageView.setImageResource(imageResource)
- binding.qrCodeLoginHeaderImageView.backgroundTintList = ColorStateList.valueOf(backgroundTint)
+ setImage(imageResource, backgroundTint)
}
- fun setTitle(title: String) {
- binding.qrCodeLoginHeaderTitleTextView.text = title
+ fun setTitle(title: String?) {
+ binding.qrCodeLoginHeaderTitleTextView.setTextOrHide(title)
}
- fun setDescription(description: String) {
- binding.qrCodeLoginHeaderDescriptionTextView.text = description
+ fun setDescription(description: String?) {
+ binding.qrCodeLoginHeaderDescriptionTextView.setTextOrHide(description)
}
fun setImage(imageResource: Int, backgroundTintColor: Int) {
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt
index ae3ba9574b..efd23f2530 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt
@@ -22,6 +22,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.activityViewModel
+import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.extensions.registerStartForActivityResult
@@ -41,32 +42,10 @@ class QrCodeLoginInstructionsFragment : VectorBaseFragment
+ if (state.loginType == QrCodeLoginType.LOGIN) {
+ views.qrCodeLoginInstructionsView.setInstructions(
+ listOf(
+ getString(R.string.qr_code_login_new_device_instruction_1),
+ getString(R.string.qr_code_login_new_device_instruction_2),
+ getString(R.string.qr_code_login_new_device_instruction_3),
+ )
+ )
+ } else {
+ views.qrCodeLoginInstructionsView.setInstructions(
+ listOf(
+ getString(R.string.qr_code_login_link_a_device_scan_qr_code_instruction_1),
+ getString(R.string.qr_code_login_link_a_device_scan_qr_code_instruction_2),
+ )
+ )
+ }
+ }
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsView.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsView.kt
index 7ef1706b37..ed5c4de175 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsView.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsView.kt
@@ -54,18 +54,19 @@ class QrCodeLoginInstructionsView @JvmOverloads constructor(
val instruction1 = typedArray.getString(R.styleable.QrCodeLoginInstructionsView_qrCodeLoginInstruction1)
val instruction2 = typedArray.getString(R.styleable.QrCodeLoginInstructionsView_qrCodeLoginInstruction2)
val instruction3 = typedArray.getString(R.styleable.QrCodeLoginInstructionsView_qrCodeLoginInstruction3)
- binding.instructions1Layout.isVisible = instruction1 != null
- binding.instructions2Layout.isVisible = instruction2 != null
- binding.instructions3Layout.isVisible = instruction3 != null
- binding.instruction1TextView.text = instruction1
- binding.instruction2TextView.text = instruction2
- binding.instruction3TextView.text = instruction3
+ setInstructions(
+ listOf(
+ instruction1,
+ instruction2,
+ instruction3,
+ )
+ )
}
- fun setInstructions(instructions: List) {
- setInstruction(binding.instructions1Layout, binding.instruction1TextView, instructions.getOrNull(0))
- setInstruction(binding.instructions2Layout, binding.instruction2TextView, instructions.getOrNull(1))
- setInstruction(binding.instructions3Layout, binding.instruction3TextView, instructions.getOrNull(2))
+ fun setInstructions(instructions: List?) {
+ setInstruction(binding.instructions1Layout, binding.instruction1TextView, instructions?.getOrNull(0))
+ setInstruction(binding.instructions2Layout, binding.instruction2TextView, instructions?.getOrNull(1))
+ setInstruction(binding.instructions3Layout, binding.instruction3TextView, instructions?.getOrNull(2))
}
private fun setInstruction(instructionLayout: LinearLayout, instructionTextView: TextView, instruction: String?) {
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginShowQrCodeFragment.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginShowQrCodeFragment.kt
index efc2c9dd08..d31f531a49 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginShowQrCodeFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginShowQrCodeFragment.kt
@@ -21,6 +21,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.activityViewModel
+import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseFragment
@@ -38,8 +39,7 @@ class QrCodeLoginShowQrCodeFragment : VectorBaseFragment
- showQrCode(qrCodeData)
- }
- }
- }
-
private fun setInstructions(loginType: QrCodeLoginType) {
if (loginType == QrCodeLoginType.LOGIN) {
views.qrCodeLoginShowQrCodeHeaderView.setDescription(getString(R.string.qr_code_login_header_show_qr_code_new_device_description))
@@ -81,4 +72,11 @@ class QrCodeLoginShowQrCodeFragment : VectorBaseFragment
+ state.generatedQrCodeData?.let { qrCodeData ->
+ showQrCode(qrCodeData)
+ }
+ setInstructions(state.loginType)
+ }
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginStatusFragment.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginStatusFragment.kt
index 405e37af15..a9c589e469 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginStatusFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginStatusFragment.kt
@@ -22,6 +22,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel
+import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseFragment
@@ -40,7 +41,6 @@ class QrCodeLoginStatusFragment : VectorBaseFragment handleConnectionEstablished(it.connectionStatus, it.loginType)
- QrCodeLoginConnectionStatus.ConnectingToDevice -> handleConnectingToDevice()
- QrCodeLoginConnectionStatus.SigningIn -> handleSigningIn()
- is QrCodeLoginConnectionStatus.Failed -> handleFailed(it.connectionStatus)
- null -> { /* NOOP */ }
- }
- }
- }
-
private fun handleFailed(connectionStatus: QrCodeLoginConnectionStatus.Failed) {
views.qrCodeLoginConfirmSecurityCodeLayout.isVisible = false
views.qrCodeLoginStatusLoadingLayout.isVisible = false
@@ -128,4 +116,14 @@ class QrCodeLoginStatusFragment : VectorBaseFragment
+ when (state.connectionStatus) {
+ is QrCodeLoginConnectionStatus.Connected -> handleConnectionEstablished(state.connectionStatus, state.loginType)
+ QrCodeLoginConnectionStatus.ConnectingToDevice -> handleConnectingToDevice()
+ QrCodeLoginConnectionStatus.SigningIn -> handleSigningIn()
+ is QrCodeLoginConnectionStatus.Failed -> handleFailed(state.connectionStatus)
+ null -> { /* NOOP */ }
+ }
+ }
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewModel.kt
index da3348653c..e979ffa63c 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewModel.kt
@@ -23,8 +23,7 @@ import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
+import timber.log.Timber
class QrCodeLoginViewModel @AssistedInject constructor(
@Assisted private val initialState: QrCodeLoginViewState,
@@ -40,7 +39,7 @@ class QrCodeLoginViewModel @AssistedInject constructor(
override fun handle(action: QrCodeLoginAction) {
when (action) {
is QrCodeLoginAction.OnQrCodeScanned -> handleOnQrCodeScanned(action)
- QrCodeLoginAction.QrCodeViewStarted -> handleQrCodeViewStarted()
+ QrCodeLoginAction.GenerateQrCode -> handleQrCodeViewStarted()
QrCodeLoginAction.ShowQrCode -> handleShowQrCode()
}
}
@@ -67,18 +66,6 @@ class QrCodeLoginViewModel @AssistedInject constructor(
}
_viewEvents.post(QrCodeLoginViewEvents.NavigateToStatusScreen)
}
-
- // TODO. UI test purpose. Fixme remove!
- viewModelScope.launch {
- delay(3000)
- onFailed(QrCodeLoginErrorType.TIMEOUT, true)
- delay(3000)
- onConnectionEstablished("1234-ABCD-5678-EFGH")
- delay(3000)
- onSigningIn()
- delay(3000)
- onFailed(QrCodeLoginErrorType.DEVICE_IS_NOT_SUPPORTED, false)
- }
}
private fun onFailed(errorType: QrCodeLoginErrorType, canTryAgain: Boolean) {
@@ -106,17 +93,14 @@ class QrCodeLoginViewModel @AssistedInject constructor(
}
}
- /**
- * TODO. UI test purpose. Fixme accordingly.
- */
+ // TODO. Implement in the logic related PR.
private fun isValidQrCode(qrCode: String): Boolean {
- return qrCode.startsWith("http")
+ Timber.d("isValidQrCode: $qrCode")
+ return false
}
- /**
- * TODO. UI test purpose. Fixme accordingly.
- */
+ // TODO. Implement in the logic related PR.
private fun generateQrCodeData(): String {
- return "https://element.io"
+ return "TODO"
}
}
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 fb8c29f39f..46b14c6d5f 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
@@ -118,7 +118,7 @@ class OnboardingViewModel @AssistedInject constructor(
}
}
- private fun observeQrCodeLoginCapability(homeServerUrl: String) = viewModelScope.launch {
+ private fun checkQrCodeLoginCapability(homeServerUrl: String) {
if (!vectorFeatures.isQrCodeLoginEnabled()) {
setState {
copy(
@@ -133,13 +133,15 @@ class OnboardingViewModel @AssistedInject constructor(
)
}
} else {
- // check if selected server supports MSC3882 first
- homeServerConnectionConfigFactory.create(homeServerUrl)?.let {
- val canLoginWithQrCode = authenticationService.isQrLoginSupported(it)
- setState {
- copy(
- canLoginWithQrCode = canLoginWithQrCode
- )
+ viewModelScope.launch {
+ // check if selected server supports MSC3882 first
+ homeServerConnectionConfigFactory.create(homeServerUrl)?.let {
+ val canLoginWithQrCode = authenticationService.isQrLoginSupported(it)
+ setState {
+ copy(
+ canLoginWithQrCode = canLoginWithQrCode
+ )
+ }
}
}
}
@@ -707,7 +709,7 @@ class OnboardingViewModel @AssistedInject constructor(
_viewEvents.post(OnboardingViewEvents.Failure(Throwable("Unable to create a HomeServerConnectionConfig")))
} else {
startAuthenticationFlow(action, homeServerConnectionConfig, serverTypeOverride, postAction)
- observeQrCodeLoginCapability(homeServerConnectionConfig.homeServerUri.toString())
+ checkQrCodeLoginCapability(homeServerConnectionConfig.homeServerUri.toString())
}
}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt
index 4d32964b7d..aad54877c9 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedLoginFragment.kt
@@ -81,20 +81,18 @@ class FtueAuthCombinedLoginFragment :
}
private fun configureQrCodeLoginButtonVisibility(canLoginWithQrCode: Boolean) {
+ views.loginWithQrCode.isVisible = canLoginWithQrCode
if (canLoginWithQrCode) {
- views.loginWithQrCode.isVisible = true
views.loginWithQrCode.debouncedClicks {
navigator
.openLoginWithQrCode(
requireActivity(),
QrCodeLoginArgs(
loginType = QrCodeLoginType.LOGIN,
- showQrCodeByDefault = false,
+ showQrCodeImmediately = false,
)
)
}
- } else {
- views.loginWithQrCode.isVisible = false
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
index d4ee1d92eb..080405c2ce 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
@@ -170,28 +170,25 @@ class VectorSettingsDevicesFragment :
views.deviceListHeaderShowQrCodeButton.isVisible = true
views.deviceListHeaderScanQrCodeButton.debouncedClicks {
- navigator
- .openLoginWithQrCode(
- requireActivity(),
- QrCodeLoginArgs(
- loginType = QrCodeLoginType.LINK_A_DEVICE,
- showQrCodeByDefault = false,
- )
- )
+ navigateToQrCodeScreen(showQrCodeImmediately = false)
}
views.deviceListHeaderShowQrCodeButton.debouncedClicks {
- navigator
- .openLoginWithQrCode(
- requireActivity(),
- QrCodeLoginArgs(
- loginType = QrCodeLoginType.LINK_A_DEVICE,
- showQrCodeByDefault = true,
- )
- )
+ navigateToQrCodeScreen(showQrCodeImmediately = true)
}
}
+ private fun navigateToQrCodeScreen(showQrCodeImmediately: Boolean) {
+ navigator
+ .openLoginWithQrCode(
+ requireActivity(),
+ QrCodeLoginArgs(
+ loginType = QrCodeLoginType.LINK_A_DEVICE,
+ showQrCodeImmediately = showQrCodeImmediately,
+ )
+ )
+ }
+
override fun onDestroyView() {
cleanUpLearnMoreButtonsListeners()
super.onDestroyView()
diff --git a/vector/src/main/res/layout/fragment_ftue_combined_login.xml b/vector/src/main/res/layout/fragment_ftue_combined_login.xml
index 17fe895cf2..7eff92f4f9 100644
--- a/vector/src/main/res/layout/fragment_ftue_combined_login.xml
+++ b/vector/src/main/res/layout/fragment_ftue_combined_login.xml
@@ -251,10 +251,12 @@
android:layout_height="60dp"
android:layout_marginTop="12dp"
android:text="@string/login_scan_qr_code"
+ android:visibility="gone"
app:drawableLeftCompat="@drawable/ic_qr_code"
app:layout_constraintEnd_toEndOf="@id/loginGutterEnd"
app:layout_constraintStart_toStartOf="@id/loginGutterStart"
- app:layout_constraintTop_toBottomOf="@id/ssoButtonsHeader" />
+ app:layout_constraintTop_toBottomOf="@id/ssoButtonsHeader"
+ tools:visibility="visible" />
-
-
-
-
-