mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
Merge pull request #1281 from vector-im/feature/various_issues_verification_ssss_bootstrap
Feature/various issues verification ssss bootstrap
This commit is contained in:
commit
4e3df99e42
@ -16,6 +16,9 @@
|
||||
|
||||
package im.vector.matrix.android.api.failure
|
||||
|
||||
import im.vector.matrix.android.api.extensions.tryThis
|
||||
import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
|
||||
fun Throwable.is401() =
|
||||
@ -37,3 +40,18 @@ fun Throwable.isInvalidPassword(): Boolean {
|
||||
&& error.code == MatrixError.M_FORBIDDEN
|
||||
&& error.message == "Invalid password"
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to convert to a RegistrationFlowResponse. Return null in the cases it's not possible
|
||||
*/
|
||||
fun Throwable.toRegistrationFlowResponse(): RegistrationFlowResponse? {
|
||||
return if (this is Failure.OtherServerError && this.httpCode == 401) {
|
||||
tryThis {
|
||||
MoshiProvider.providesMoshi()
|
||||
.adapter(RegistrationFlowResponse::class.java)
|
||||
.fromJson(this.errorBody)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ package im.vector.matrix.android.internal.auth.registration
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.failure.toRegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.auth.AuthAPI
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
|
||||
@ -39,25 +39,9 @@ internal class DefaultRegisterTask(
|
||||
apiCall = authAPI.register(params.registrationParams)
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is Failure.OtherServerError && throwable.httpCode == 401) {
|
||||
// Parse to get a RegistrationFlowResponse
|
||||
val registrationFlowResponse = try {
|
||||
MoshiProvider.providesMoshi()
|
||||
.adapter(RegistrationFlowResponse::class.java)
|
||||
.fromJson(throwable.errorBody)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
// check if the server response can be cast
|
||||
if (registrationFlowResponse != null) {
|
||||
throw Failure.RegistrationFlowError(registrationFlowResponse)
|
||||
} else {
|
||||
throw throwable
|
||||
}
|
||||
} else {
|
||||
// Other error
|
||||
throw throwable
|
||||
}
|
||||
throw throwable.toRegistrationFlowResponse()
|
||||
?.let { Failure.RegistrationFlowError(it) }
|
||||
?: throwable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,9 @@
|
||||
package im.vector.matrix.android.internal.crypto.tasks
|
||||
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
|
||||
import im.vector.matrix.android.api.failure.toRegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.DeleteDeviceParams
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -43,25 +42,9 @@ internal class DefaultDeleteDeviceTask @Inject constructor(
|
||||
apiCall = cryptoApi.deleteDevice(params.deviceId, DeleteDeviceParams())
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is Failure.OtherServerError && throwable.httpCode == 401) {
|
||||
// Parse to get a RegistrationFlowResponse
|
||||
val registrationFlowResponse = try {
|
||||
MoshiProvider.providesMoshi()
|
||||
.adapter(RegistrationFlowResponse::class.java)
|
||||
.fromJson(throwable.errorBody)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
// check if the server response can be casted
|
||||
if (registrationFlowResponse != null) {
|
||||
throw Failure.RegistrationFlowError(registrationFlowResponse)
|
||||
} else {
|
||||
throw throwable
|
||||
}
|
||||
} else {
|
||||
// Other error
|
||||
throw throwable
|
||||
}
|
||||
throw throwable.toRegistrationFlowResponse()
|
||||
?.let { Failure.RegistrationFlowError(it) }
|
||||
?: throwable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,14 +17,13 @@
|
||||
package im.vector.matrix.android.internal.crypto.tasks
|
||||
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
|
||||
import im.vector.matrix.android.api.failure.toRegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
||||
import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.KeysQueryResponse
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.UploadSigningKeysBody
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
||||
import im.vector.matrix.android.internal.crypto.model.toRest
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -65,37 +64,25 @@ internal class DefaultUploadSigningKeysTask @Inject constructor(
|
||||
}
|
||||
return
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is Failure.OtherServerError
|
||||
&& throwable.httpCode == 401
|
||||
val registrationFlowResponse = throwable.toRegistrationFlowResponse()
|
||||
if (registrationFlowResponse != null
|
||||
&& params.userPasswordAuth != null
|
||||
/* Avoid infinite loop */
|
||||
&& params.userPasswordAuth.session.isNullOrEmpty()
|
||||
) {
|
||||
try {
|
||||
MoshiProvider.providesMoshi()
|
||||
.adapter(RegistrationFlowResponse::class.java)
|
||||
.fromJson(throwable.errorBody)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}?.let {
|
||||
// Retry with authentication
|
||||
try {
|
||||
val req = executeRequest<KeysQueryResponse>(eventBus) {
|
||||
apiCall = cryptoApi.uploadSigningKeys(
|
||||
uploadQuery.copy(auth = params.userPasswordAuth.copy(session = it.session))
|
||||
uploadQuery.copy(auth = params.userPasswordAuth.copy(session = registrationFlowResponse.session))
|
||||
)
|
||||
}
|
||||
if (req.failures?.isNotEmpty() == true) {
|
||||
throw UploadSigningKeys(req.failures)
|
||||
}
|
||||
return
|
||||
} catch (failure: Throwable) {
|
||||
throw failure
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Other error
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,7 @@
|
||||
|
||||
package im.vector.matrix.android.internal.session.account
|
||||
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.api.failure.toRegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.di.UserId
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
@ -45,31 +43,20 @@ internal class DefaultChangePasswordTask @Inject constructor(
|
||||
apiCall = accountAPI.changePassword(changePasswordParams)
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is Failure.OtherServerError
|
||||
&& throwable.httpCode == 401
|
||||
val registrationFlowResponse = throwable.toRegistrationFlowResponse()
|
||||
|
||||
if (registrationFlowResponse != null
|
||||
/* Avoid infinite loop */
|
||||
&& changePasswordParams.auth?.session == null) {
|
||||
try {
|
||||
MoshiProvider.providesMoshi()
|
||||
.adapter(RegistrationFlowResponse::class.java)
|
||||
.fromJson(throwable.errorBody)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}?.let {
|
||||
// Retry with authentication
|
||||
try {
|
||||
executeRequest<Unit>(eventBus) {
|
||||
apiCall = accountAPI.changePassword(
|
||||
changePasswordParams.copy(auth = changePasswordParams.auth?.copy(session = it.session))
|
||||
changePasswordParams.copy(auth = changePasswordParams.auth?.copy(session = registrationFlowResponse.session))
|
||||
)
|
||||
}
|
||||
return
|
||||
} catch (failure: Throwable) {
|
||||
throw failure
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +95,14 @@ class BootstrapConfirmPassphraseFragment @Inject constructor(
|
||||
sharedViewModel.handle(BootstrapActions.TogglePasswordVisibility)
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
bootstrapSubmit.clicks()
|
||||
.debounce(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
submit()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
||||
private fun submit() = withState(sharedViewModel) { state ->
|
||||
@ -113,8 +121,6 @@ class BootstrapConfirmPassphraseFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(sharedViewModel) { state ->
|
||||
super.invalidate()
|
||||
|
||||
if (state.step is BootstrapStep.ConfirmPassphrase) {
|
||||
val isPasswordVisible = state.step.isPasswordVisible
|
||||
ssss_passphrase_enter_edittext.showPassword(isPasswordVisible, updateCursor = false)
|
||||
|
@ -18,6 +18,7 @@ package im.vector.riotx.features.crypto.recover
|
||||
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.failure.MatrixError
|
||||
import im.vector.matrix.android.api.failure.toRegistrationFlowResponse
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
||||
@ -28,13 +29,11 @@ import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageSer
|
||||
import im.vector.matrix.android.api.session.securestorage.SsssKeyCreationInfo
|
||||
import im.vector.matrix.android.api.session.securestorage.SsssKeySpec
|
||||
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
||||
import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.crypto.crosssigning.toBase64NoPadding
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersion
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.util.awaitCallback
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.platform.ViewModelTask
|
||||
@ -230,15 +229,10 @@ class BootstrapCrossSigningTask @Inject constructor(
|
||||
private fun handleInitializeXSigningError(failure: Throwable): BootstrapResult {
|
||||
if (failure is Failure.ServerError && failure.error.code == MatrixError.M_FORBIDDEN) {
|
||||
return BootstrapResult.InvalidPasswordError(failure.error)
|
||||
} else if (failure is Failure.OtherServerError && failure.httpCode == 401) {
|
||||
try {
|
||||
MoshiProvider.providesMoshi()
|
||||
.adapter(RegistrationFlowResponse::class.java)
|
||||
.fromJson(failure.errorBody)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}?.let { flowResponse ->
|
||||
if (flowResponse.flows?.any { it.stages?.contains(LoginFlowTypes.PASSWORD) == true } != true) {
|
||||
} else {
|
||||
val registrationFlowResponse = failure.toRegistrationFlowResponse()
|
||||
if (registrationFlowResponse != null) {
|
||||
if (registrationFlowResponse.flows?.any { it.stages?.contains(LoginFlowTypes.PASSWORD) == true } != true) {
|
||||
// can't do this from here
|
||||
return BootstrapResult.UnsupportedAuthFlow()
|
||||
}
|
||||
|
@ -90,6 +90,14 @@ class BootstrapEnterPassphraseFragment @Inject constructor(
|
||||
sharedViewModel.handle(BootstrapActions.TogglePasswordVisibility)
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
bootstrapSubmit.clicks()
|
||||
.debounce(300, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
submit()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
||||
private fun submit() = withState(sharedViewModel) { state ->
|
||||
@ -108,8 +116,6 @@ class BootstrapEnterPassphraseFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(sharedViewModel) { state ->
|
||||
super.invalidate()
|
||||
|
||||
if (state.step is BootstrapStep.SetupPassphrase) {
|
||||
val isPasswordVisible = state.step.isPasswordVisible
|
||||
ssss_passphrase_enter_edittext.showPassword(isPasswordVisible, updateCursor = false)
|
||||
|
@ -167,6 +167,8 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||
val crossSigningEnabledOnAccount = myCrossSigningKeys != null
|
||||
|
||||
if (!crossSigningEnabledOnAccount && !sharedActionViewModel.isAccountCreation) {
|
||||
// Do not propose for SSO accounts, because we do not support yet confirming account credentials using SSO
|
||||
if (session.getHomeServerCapabilities().canChangePassword) {
|
||||
// We need to ask
|
||||
promptSecurityEvent(
|
||||
session,
|
||||
@ -175,6 +177,10 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||
) {
|
||||
it.navigator.upgradeSessionSecurity(it)
|
||||
}
|
||||
} else {
|
||||
// Do not do it again
|
||||
sharedActionViewModel.hasDisplayedCompleteSecurityPrompt = true
|
||||
}
|
||||
} else if (myCrossSigningKeys?.isTrusted() == false) {
|
||||
// We need to ask
|
||||
promptSecurityEvent(
|
||||
|
@ -37,7 +37,6 @@ class CrossSigningEpoxyController @Inject constructor(
|
||||
|
||||
interface InteractionListener {
|
||||
fun onInitializeCrossSigningKeys()
|
||||
fun onResetCrossSigningKeys()
|
||||
fun verifySession()
|
||||
}
|
||||
|
||||
@ -51,18 +50,6 @@ class CrossSigningEpoxyController @Inject constructor(
|
||||
titleIconResourceId(R.drawable.ic_shield_trusted)
|
||||
title(stringProvider.getString(R.string.encryption_information_dg_xsigning_complete))
|
||||
}
|
||||
if (vectorPreferences.developerMode() && !data.isUploadingKeys) {
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (data.xSigningKeysAreTrusted) {
|
||||
genericItem {
|
||||
id("trusted")
|
||||
@ -70,19 +57,6 @@ class CrossSigningEpoxyController @Inject constructor(
|
||||
title(stringProvider.getString(R.string.encryption_information_dg_xsigning_trusted))
|
||||
}
|
||||
if (!data.isUploadingKeys) {
|
||||
if (vectorPreferences.developerMode()) {
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bottomSheetVerificationActionItem {
|
||||
id("verify")
|
||||
title(stringProvider.getString(R.string.complete_security))
|
||||
@ -110,18 +84,6 @@ class CrossSigningEpoxyController @Inject constructor(
|
||||
interactionListener?.verifySession()
|
||||
}
|
||||
}
|
||||
if (vectorPreferences.developerMode()) {
|
||||
bottomSheetVerificationActionItem {
|
||||
id("resetkeys")
|
||||
title("Reset keys")
|
||||
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||
listener {
|
||||
interactionListener?.onResetCrossSigningKeys()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
genericItem {
|
||||
id("not")
|
||||
@ -130,7 +92,7 @@ class CrossSigningEpoxyController @Inject constructor(
|
||||
if (vectorPreferences.developerMode() && !data.isUploadingKeys) {
|
||||
bottomSheetVerificationActionItem {
|
||||
id("initKeys")
|
||||
title("Initialize keys")
|
||||
title(stringProvider.getString(R.string.initialize_cross_signing))
|
||||
titleColor(colorProvider.getColor(R.color.riotx_positive_accent))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(colorProvider.getColor(R.color.riotx_positive_accent))
|
||||
|
@ -101,14 +101,4 @@ class CrossSigningSettingsFragment @Inject constructor(
|
||||
override fun verifySession() {
|
||||
viewModel.handle(CrossSigningAction.VerifySession)
|
||||
}
|
||||
|
||||
override fun onResetCrossSigningKeys() {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.dialog_title_confirmation)
|
||||
.setMessage(R.string.are_you_sure)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
viewModel.handle(CrossSigningAction.InitializeCrossSigning)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,12 @@ import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.failure.toRegistrationFlowResponse
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo
|
||||
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
||||
import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.crypto.crosssigning.isVerified
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
@ -113,19 +111,12 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(@Assisted privat
|
||||
override fun onFailure(failure: Throwable) {
|
||||
_pendingSession = null
|
||||
|
||||
if (failure is Failure.OtherServerError && failure.httpCode == 401) {
|
||||
try {
|
||||
MoshiProvider.providesMoshi()
|
||||
.adapter(RegistrationFlowResponse::class.java)
|
||||
.fromJson(failure.errorBody)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}?.let { flowResponse ->
|
||||
val registrationFlowResponse = failure.toRegistrationFlowResponse()
|
||||
if (registrationFlowResponse != null) {
|
||||
// Retry with authentication
|
||||
if (flowResponse.flows?.any { it.stages?.contains(LoginFlowTypes.PASSWORD) == true } == true) {
|
||||
_pendingSession = flowResponse.session ?: ""
|
||||
if (registrationFlowResponse.flows?.any { it.stages?.contains(LoginFlowTypes.PASSWORD) == true } == true) {
|
||||
_pendingSession = registrationFlowResponse.session ?: ""
|
||||
_viewEvents.post(CrossSigningSettingsViewEvents.RequestPassword)
|
||||
return
|
||||
} else {
|
||||
// can't do this from here
|
||||
_viewEvents.post(CrossSigningSettingsViewEvents.Failure(Throwable("You cannot do that from mobile")))
|
||||
@ -133,17 +124,15 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(@Assisted privat
|
||||
setState {
|
||||
copy(isUploadingKeys = false)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
_viewEvents.post(CrossSigningSettingsViewEvents.Failure(failure))
|
||||
|
||||
setState {
|
||||
copy(isUploadingKeys = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
@ -12,10 +11,9 @@
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:layout_height="wrap_content">
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bootstrapIcon"
|
||||
@ -28,23 +26,19 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bootstrapTitleText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/bootstrapIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/bootstrapIcon"
|
||||
app:layout_constraintTop_toTopOf="@+id/bootstrapIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/recovery_passphrase" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
|
@ -44,13 +44,11 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/verificationRequestAvatar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/verificationRequestAvatar"
|
||||
app:layout_constraintTop_toTopOf="@+id/verificationRequestAvatar"
|
||||
|
@ -12,11 +12,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
tools:text="@string/enter_account_password"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/bootstrapAccountPasswordTil"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/enter_account_password" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/bootstrapAccountPasswordTil"
|
||||
@ -59,9 +59,7 @@
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/bootstrapPasswordButton"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="@dimen/layout_vertical_margin"
|
||||
android:padding="8dp"
|
||||
android:text="@string/_continue"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
@ -25,7 +24,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:errorEnabled="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/ssss_view_show_password"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/bootstrapDescriptionText">
|
||||
@ -34,11 +32,11 @@
|
||||
android:id="@+id/ssss_passphrase_enter_edittext"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:hint="@string/passphrase_enter_passphrase"
|
||||
android:imeOptions="actionDone"
|
||||
android:maxLines="3"
|
||||
android:singleLine="false"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:hint="@string/passphrase_enter_passphrase"
|
||||
tools:inputType="textPassword" />
|
||||
|
||||
<!-- This is inside the TIL, if not the keyboard will hide it when in bottomsheet -->
|
||||
@ -46,9 +44,9 @@
|
||||
<im.vector.riotx.core.ui.views.PasswordStrengthBar
|
||||
android:id="@+id/ssss_passphrase_security_progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginBottom="2dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_height="4dp" />
|
||||
android:layout_marginBottom="2dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bootstrapWarningInfo"
|
||||
@ -56,12 +54,12 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center_vertical"
|
||||
android:drawableStart="@drawable/ic_alert_triangle"
|
||||
android:drawableTint="@color/riotx_destructive_accent"
|
||||
android:drawablePadding="4dp"
|
||||
android:text="@string/bootstrap_dont_reuse_pwd" />
|
||||
android:drawableTint="@color/riotx_destructive_accent"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/bootstrap_dont_reuse_pwd"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
@ -78,6 +76,13 @@
|
||||
app:layout_constraintStart_toEndOf="@+id/ssss_passphrase_enter_til"
|
||||
app:layout_constraintTop_toTopOf="@+id/ssss_passphrase_enter_til" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/bootstrapSubmit"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:text="@string/_continue"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/ssss_passphrase_enter_til" />
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/bootstrapWarningInfo"-->
|
||||
|
@ -79,7 +79,6 @@
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/bootstrapMigrateContinueButton"
|
||||
style="@style/VectorButtonStyleText"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="@dimen/layout_vertical_margin"
|
||||
android:text="@string/_continue"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
Loading…
Reference in New Issue
Block a user