Merge pull request #2465 from vector-im/feature/bca/fix_verifypassphrase_bottomsheet
Fix / double bottomsheet effect
This commit is contained in:
commit
d759636d95
|
@ -8,7 +8,7 @@ Improvements 🙌:
|
||||||
-
|
-
|
||||||
|
|
||||||
Bugfix 🐛:
|
Bugfix 🐛:
|
||||||
-
|
- Double bottomsheet effect after verify with passphrase
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
|
|
@ -36,6 +36,7 @@ import im.vector.app.features.crypto.recover.BootstrapMigrateBackupFragment
|
||||||
import im.vector.app.features.crypto.recover.BootstrapSaveRecoveryKeyFragment
|
import im.vector.app.features.crypto.recover.BootstrapSaveRecoveryKeyFragment
|
||||||
import im.vector.app.features.crypto.recover.BootstrapSetupRecoveryKeyFragment
|
import im.vector.app.features.crypto.recover.BootstrapSetupRecoveryKeyFragment
|
||||||
import im.vector.app.features.crypto.recover.BootstrapWaitingFragment
|
import im.vector.app.features.crypto.recover.BootstrapWaitingFragment
|
||||||
|
import im.vector.app.features.crypto.verification.QuadSLoadingFragment
|
||||||
import im.vector.app.features.crypto.verification.cancel.VerificationCancelFragment
|
import im.vector.app.features.crypto.verification.cancel.VerificationCancelFragment
|
||||||
import im.vector.app.features.crypto.verification.cancel.VerificationNotMeFragment
|
import im.vector.app.features.crypto.verification.cancel.VerificationNotMeFragment
|
||||||
import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodFragment
|
import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodFragment
|
||||||
|
@ -418,6 +419,11 @@ interface FragmentModule {
|
||||||
@FragmentKey(VerificationCancelFragment::class)
|
@FragmentKey(VerificationCancelFragment::class)
|
||||||
fun bindVerificationCancelFragment(fragment: VerificationCancelFragment): Fragment
|
fun bindVerificationCancelFragment(fragment: VerificationCancelFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(QuadSLoadingFragment::class)
|
||||||
|
fun bindQuadSLoadingFragment(fragment: QuadSLoadingFragment): Fragment
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FragmentKey(VerificationNotMeFragment::class)
|
@FragmentKey(VerificationNotMeFragment::class)
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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.crypto.verification
|
||||||
|
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class QuadSLoadingFragment @Inject constructor() : VectorBaseFragment() {
|
||||||
|
override fun getLayoutResId() = R.layout.fragment_progress
|
||||||
|
}
|
|
@ -31,5 +31,6 @@ sealed class VerificationAction : VectorViewModelAction {
|
||||||
object SkipVerification : VerificationAction()
|
object SkipVerification : VerificationAction()
|
||||||
object VerifyFromPassphrase : VerificationAction()
|
object VerifyFromPassphrase : VerificationAction()
|
||||||
data class GotResultFromSsss(val cypherData: String, val alias: String) : VerificationAction()
|
data class GotResultFromSsss(val cypherData: String, val alias: String) : VerificationAction()
|
||||||
|
object CancelledFromSsss : VerificationAction()
|
||||||
object SecuredStorageHasBeenReset : VerificationAction()
|
object SecuredStorageHasBeenReset : VerificationAction()
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,8 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
// all have been reset, so we are verified?
|
// all have been reset, so we are verified?
|
||||||
viewModel.handle(VerificationAction.SecuredStorageHasBeenReset)
|
viewModel.handle(VerificationAction.SecuredStorageHasBeenReset)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
viewModel.handle(VerificationAction.CancelledFromSsss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,6 +211,10 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
return@withState
|
return@withState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.selfVerificationMode && state.verifyingFrom4S) {
|
||||||
|
showFragment(QuadSLoadingFragment::class, Bundle())
|
||||||
|
return@withState
|
||||||
|
}
|
||||||
if (state.selfVerificationMode && state.verifiedFromPrivateKeys) {
|
if (state.selfVerificationMode && state.verifiedFromPrivateKeys) {
|
||||||
showFragment(VerificationConclusionFragment::class, Bundle().apply {
|
showFragment(VerificationConclusionFragment::class, Bundle().apply {
|
||||||
putParcelable(MvRx.KEY_ARG, VerificationConclusionFragment.Args(true, null, state.isMe))
|
putParcelable(MvRx.KEY_ARG, VerificationConclusionFragment.Args(true, null, state.isMe))
|
||||||
|
|
|
@ -32,6 +32,7 @@ import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
@ -70,6 +71,7 @@ data class VerificationBottomSheetViewState(
|
||||||
// true when we display the loading and we wait for the other (incoming request)
|
// true when we display the loading and we wait for the other (incoming request)
|
||||||
val selfVerificationMode: Boolean = false,
|
val selfVerificationMode: Boolean = false,
|
||||||
val verifiedFromPrivateKeys: Boolean = false,
|
val verifiedFromPrivateKeys: Boolean = false,
|
||||||
|
val verifyingFrom4S: Boolean = false,
|
||||||
val isMe: Boolean = false,
|
val isMe: Boolean = false,
|
||||||
val currentDeviceCanCrossSign: Boolean = false,
|
val currentDeviceCanCrossSign: Boolean = false,
|
||||||
val userWantsToCancel: Boolean = false,
|
val userWantsToCancel: Boolean = false,
|
||||||
|
@ -170,7 +172,9 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if the verification is already done you can't cancel anymore
|
// if the verification is already done you can't cancel anymore
|
||||||
if (state.pendingRequest.invoke()?.cancelConclusion != null || state.sasTransactionState is VerificationTxState.TerminalTxState) {
|
if (state.pendingRequest.invoke()?.cancelConclusion != null
|
||||||
|
|| state.sasTransactionState is VerificationTxState.TerminalTxState
|
||||||
|
|| state.verifyingFrom4S) {
|
||||||
// you cannot cancel anymore
|
// you cannot cancel anymore
|
||||||
} else {
|
} else {
|
||||||
setState {
|
setState {
|
||||||
|
@ -346,6 +350,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||||
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
|
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
|
||||||
}
|
}
|
||||||
is VerificationAction.VerifyFromPassphrase -> {
|
is VerificationAction.VerifyFromPassphrase -> {
|
||||||
|
setState { copy(verifyingFrom4S = true) }
|
||||||
_viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore)
|
_viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore)
|
||||||
}
|
}
|
||||||
is VerificationAction.GotResultFromSsss -> {
|
is VerificationAction.GotResultFromSsss -> {
|
||||||
|
@ -354,56 +359,73 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||||
VerificationAction.SecuredStorageHasBeenReset -> {
|
VerificationAction.SecuredStorageHasBeenReset -> {
|
||||||
if (session.cryptoService().crossSigningService().allPrivateKeysKnown()) {
|
if (session.cryptoService().crossSigningService().allPrivateKeysKnown()) {
|
||||||
setState {
|
setState {
|
||||||
copy(quadSHasBeenReset = true)
|
copy(quadSHasBeenReset = true, verifyingFrom4S = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
|
VerificationAction.CancelledFromSsss -> {
|
||||||
|
setState {
|
||||||
|
copy(verifyingFrom4S = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
|
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
|
||||||
try {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
action.cypherData.fromBase64().inputStream().use { ins ->
|
try {
|
||||||
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
action.cypherData.fromBase64().inputStream().use { ins ->
|
||||||
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
|
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
||||||
res?.get(MASTER_KEY_SSSS_NAME),
|
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
|
||||||
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
res?.get(MASTER_KEY_SSSS_NAME),
|
||||||
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
||||||
)
|
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
||||||
if (trustResult.isVerified()) {
|
)
|
||||||
// Sign this device and upload the signature
|
if (trustResult.isVerified()) {
|
||||||
session.sessionParams.deviceId?.let { deviceId ->
|
// Sign this device and upload the signature
|
||||||
session.cryptoService()
|
session.sessionParams.deviceId?.let { deviceId ->
|
||||||
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
|
session.cryptoService()
|
||||||
override fun onFailure(failure: Throwable) {
|
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
|
||||||
Timber.w(failure, "Failed to sign my device after recovery")
|
override fun onFailure(failure: Throwable) {
|
||||||
}
|
Timber.w(failure, "Failed to sign my device after recovery")
|
||||||
})
|
}
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
|
||||||
setState {
|
setState {
|
||||||
copy(verifiedFromPrivateKeys = true)
|
copy(
|
||||||
}
|
verifyingFrom4S = false,
|
||||||
|
verifiedFromPrivateKeys = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// try to get keybackup key
|
// try the keybackup
|
||||||
} else {
|
tentativeRestoreBackup(res)
|
||||||
// POP UP something
|
} else {
|
||||||
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys)))
|
setState {
|
||||||
|
copy(
|
||||||
|
verifyingFrom4S = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// POP UP something
|
||||||
|
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (failure: Throwable) {
|
||||||
// try the keybackup
|
setState {
|
||||||
tentativeRestoreBackup(res)
|
copy(
|
||||||
Unit
|
verifyingFrom4S = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_viewEvents.post(
|
||||||
|
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
|
||||||
}
|
}
|
||||||
} catch (failure: Throwable) {
|
|
||||||
_viewEvents.post(
|
|
||||||
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tentativeRestoreBackup(res: Map<String, String>?) {
|
private fun tentativeRestoreBackup(res: Map<String, String>?) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also {
|
val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also {
|
||||||
Timber.v("## Keybackup secret not restored from SSSS")
|
Timber.v("## Keybackup secret not restored from SSSS")
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_marginTop="@dimen/layout_vertical_margin_big"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
Loading…
Reference in New Issue