diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index 907940414f..fbe62d03ed 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -2510,6 +2510,8 @@
This wasn’t me
Your account may be compromised
+ Resume
+
If you cancel, you won’t be able to read encrypted messages on this device, and other users won’t trust it
If you cancel, you won’t be able to read encrypted messages on your new device, and other users won’t trust it
You won’t verify %1$s (%2$s) if you cancel now. Start again in their user profile.
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationAction.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationAction.kt
index 617e31d8fa..0b535da8fe 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationAction.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationAction.kt
@@ -18,7 +18,6 @@ package im.vector.app.features.crypto.verification
import im.vector.app.core.platform.VectorViewModelAction
-// TODO Remove otherUserId and transactionId when it's not necessary. Should be known by the ViewModel, no?
sealed class VerificationAction : VectorViewModelAction {
object RequestVerificationByDM : VerificationAction()
object RequestSelfVerification : VerificationAction()
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt
deleted file mode 100644
index 8580a324a3..0000000000
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt
+++ /dev/null
@@ -1,439 +0,0 @@
-// /*
-// * Copyright 2019 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 android.app.Activity
-// import android.app.Dialog
-// import android.os.Bundle
-// import android.os.Parcelable
-// import android.view.KeyEvent
-// import android.view.LayoutInflater
-// import android.view.View
-// import android.view.ViewGroup
-// import androidx.fragment.app.Fragment
-// import com.airbnb.mvrx.fragmentViewModel
-// import com.airbnb.mvrx.withState
-// import com.google.android.material.dialog.MaterialAlertDialogBuilder
-// import dagger.hilt.android.AndroidEntryPoint
-// import im.vector.app.R
-// import im.vector.app.core.extensions.commitTransaction
-// import im.vector.app.core.extensions.registerStartForActivityResult
-// import im.vector.app.core.extensions.toMvRxBundle
-// import im.vector.app.core.platform.VectorBaseActivity
-// import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
-// import im.vector.app.databinding.BottomSheetVerificationBinding
-// import im.vector.app.features.crypto.quads.SharedSecureStorageActivity
-// 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.choose.VerificationChooseMethodFragment
-// import im.vector.app.features.crypto.verification.conclusion.VerificationConclusionFragment
-// import im.vector.app.features.crypto.verification.emoji.VerificationEmojiCodeFragment
-// import im.vector.app.features.crypto.verification.qrconfirmation.VerificationQRWaitingFragment
-// import im.vector.app.features.crypto.verification.qrconfirmation.VerificationQrScannedByOtherFragment
-// import im.vector.app.features.crypto.verification.request.VerificationRequestFragment
-// import im.vector.app.features.displayname.getBestName
-// import im.vector.app.features.home.AvatarRenderer
-// import im.vector.app.features.settings.VectorSettingsActivity
-// import kotlinx.parcelize.Parcelize
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
-// import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
-// import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
-// import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState
-// import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
-// import timber.log.Timber
-// import javax.inject.Inject
-// import kotlin.reflect.KClass
-//
-// @AndroidEntryPoint
-// class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
-//
-// @Parcelize
-// data class VerificationArgs(
-// val otherUserId: String,
-// // might be null for self verification if there is no device to request to
-// // in this case you could use 4S (or reset all)
-// val verificationId: String?,
-// // val verificationLocalId: String? = null,
-// val roomId: String? = null,
-// // Special mode where UX should show loading wheel until other session sends a request/tx
-// val selfVerificationMode: Boolean = false
-// ) : Parcelable
-//
-// override val showExpanded = true
-//
-// @Inject
-// lateinit var avatarRenderer: AvatarRenderer
-//
-// private val viewModel by fragmentViewModel(VerificationBottomSheetViewModel::class)
-//
-// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationBinding {
-// return BottomSheetVerificationBinding.inflate(inflater, container, false)
-// }
-//
-// init {
-// isCancelable = false
-// }
-//
-// override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-// super.onViewCreated(view, savedInstanceState)
-//
-// viewModel.observeViewEvents {
-// when (it) {
-// is VerificationBottomSheetViewEvents.Dismiss -> dismiss()
-// is VerificationBottomSheetViewEvents.AccessSecretStore -> {
-// secretStartForActivityResult.launch(
-// SharedSecureStorageActivity.newReadIntent(
-// requireContext(),
-// null, // use default key
-// listOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME),
-// SharedSecureStorageActivity.DEFAULT_RESULT_KEYSTORE_ALIAS
-// )
-// )
-// }
-// is VerificationBottomSheetViewEvents.ModalError -> {
-// MaterialAlertDialogBuilder(requireContext())
-// .setTitle(getString(R.string.dialog_title_error))
-// .setMessage(it.errorMessage)
-// .setCancelable(false)
-// .setPositiveButton(R.string.ok, null)
-// .show()
-// Unit
-// }
-// VerificationBottomSheetViewEvents.GoToSettings -> {
-// dismiss()
-// (activity as? VectorBaseActivity<*>)?.let { activity ->
-// activity.navigator.openSettings(activity, VectorSettingsActivity.EXTRA_DIRECT_ACCESS_SECURITY_PRIVACY)
-// }
-// }
-// }
-// }
-// }
-//
-// override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
-// return super.onCreateDialog(savedInstanceState).apply {
-// setOnKeyListener { _, keyCode, keyEvent ->
-// if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == KeyEvent.ACTION_UP) {
-// viewModel.queryCancel()
-// true
-// } else {
-// false
-// }
-// }
-// }
-// }
-//
-// private val secretStartForActivityResult = registerStartForActivityResult { activityResult ->
-// if (activityResult.resultCode == Activity.RESULT_OK) {
-// val result = activityResult.data?.getStringExtra(SharedSecureStorageActivity.EXTRA_DATA_RESULT)
-// val reset = activityResult.data?.getBooleanExtra(SharedSecureStorageActivity.EXTRA_DATA_RESET, false) ?: false
-// if (result != null) {
-// viewModel.handle(VerificationAction.GotResultFromSsss(result, SharedSecureStorageActivity.DEFAULT_RESULT_KEYSTORE_ALIAS))
-// } else if (reset) {
-// // all have been reset, so we are verified?
-// viewModel.handle(VerificationAction.SecuredStorageHasBeenReset)
-// }
-// } else {
-// viewModel.handle(VerificationAction.CancelledFromSsss)
-// }
-// }
-//
-// override fun invalidate() = withState(viewModel) { state ->
-// avatarRenderer.render(state.otherUserMxItem, views.otherUserAvatarImageView)
-// if (state.isMe) {
-// if (state.sasTransactionState == VerificationTxState.Verified ||
-// state.qrTransactionState == VerificationTxState.Verified ||
-// state.verifiedFromPrivateKeys) {
-// views.otherUserShield.render(RoomEncryptionTrustLevel.Trusted)
-// } else {
-// views.otherUserShield.render(RoomEncryptionTrustLevel.Warning)
-// }
-// views.otherUserNameText.text = getString(
-// if (state.selfVerificationMode) R.string.crosssigning_verify_this_session else R.string.crosssigning_verify_session
-// )
-// } else {
-// if (state.sasTransactionState == VerificationTxState.Verified || state.qrTransactionState == VerificationTxState.Verified) {
-// views.otherUserNameText.text = getString(R.string.verification_verified_user, state.otherUserMxItem.getBestName())
-// views.otherUserShield.render(RoomEncryptionTrustLevel.Trusted)
-// } else {
-// views.otherUserNameText.text = getString(R.string.verification_verify_user, state.otherUserMxItem.getBestName())
-// views.otherUserShield.render(null)
-// }
-// }
-//
-// if (state.quadSHasBeenReset) {
-// showFragment(
-// VerificationConclusionFragment::class,
-// VerificationConclusionFragment.Args(
-// isSuccessFull = true,
-// isMe = true,
-// cancelReason = null
-// )
-// )
-// return@withState
-// }
-//
-// if (state.userThinkItsNotHim) {
-// views.otherUserNameText.text = getString(R.string.dialog_title_warning)
-// showFragment(VerificationNotMeFragment::class)
-// return@withState
-// }
-//
-// if (state.userWantsToCancel) {
-// views.otherUserNameText.text = getString(R.string.are_you_sure)
-// showFragment(VerificationCancelFragment::class)
-// return@withState
-// }
-//
-// if (state.selfVerificationMode && state.verifyingFrom4S) {
-// showFragment(QuadSLoadingFragment::class)
-// return@withState
-// }
-// if (state.selfVerificationMode && state.verifiedFromPrivateKeys) {
-// showFragment(
-// VerificationConclusionFragment::class,
-// VerificationConclusionFragment.Args(true, null, state.isMe)
-// )
-// return@withState
-// }
-//
-// // Did the request result in a SAS transaction?
-// if (state.sasTransactionState != null) {
-// when (state.sasTransactionState) {
-//
-// VerificationTxState.None,
-// VerificationTxState.SasStarted,
-// VerificationTxState.SasKeySent,
-// VerificationTxState.SasShortCodeReady,
-// VerificationTxState.SasMacSent,
-// is VerificationTxState.SasMacReceived,
-// VerificationTxState.SasAccepted -> {
-// showFragment(
-// VerificationEmojiCodeFragment::class,
-// VerificationArgs(
-// state.otherUserId,
-// // If it was outgoing it.transaction id would be null, but the pending request
-// // would be updated (from localId to txId)
-// state.pendingRequest.invoke()?.transactionId ?: state.transactionId
-// )
-// )
-// }
-// is VerificationTxState.Verified -> {
-// showFragment(
-// VerificationConclusionFragment::class,
-// VerificationConclusionFragment.Args(true, null, state.isMe)
-// )
-// }
-// is VerificationTxState.Cancelled -> {
-// showFragment(
-// VerificationConclusionFragment::class,
-// VerificationConclusionFragment.Args(false, state.sasTransactionState.cancelCode.value, state.isMe)
-// )
-// }
-// else -> Unit
-// // is VerificationTxState.None,
-// // is VerificationTxState.SendingStart,
-// // is VerificationTxState.Started,
-// // is VerificationTxState.OnStarted,
-// // is VerificationTxState.SendingAccept,
-// // is VerificationTxState.Accepted,
-// // is VerificationTxState.OnAccepted,
-// // is VerificationTxState.SendingKey,
-// // is VerificationTxState.KeySent,
-// // is VerificationTxState.OnKeyReceived,
-// // is VerificationTxState.ShortCodeReady,
-// // is VerificationTxState.ShortCodeAccepted,
-// // is VerificationTxState.SendingMac,
-// // is VerificationTxState.MacSent,
-// // is VerificationTxState.Verifying -> {
-// // showFragment(
-// // VerificationEmojiCodeFragment::class,
-// // VerificationArgs(
-// // state.otherUserId,
-// // // If it was outgoing it.transaction id would be null, but the pending request
-// // // would be updated (from localId to txId)
-// // state.pendingRequest.invoke()?.transactionId ?: state.transactionId
-// // )
-// // )
-// // }
-// // is VerificationTxState.Verified -> {
-// // showFragment(
-// // VerificationConclusionFragment::class,
-// // VerificationConclusionFragment.Args(true, null, state.isMe)
-// // )
-// // }
-// // is VerificationTxState.Cancelled -> {
-// // showFragment(
-// // VerificationConclusionFragment::class,
-// // VerificationConclusionFragment.Args(false, state.sasTransactionState.cancelCode.value, state.isMe)
-// // )
-// // }
-// // else -> Unit
-// }
-//
-// return@withState
-// }
-//
-// when (state.qrTransactionState) {
-// is VerificationTxState.QrScannedByOther -> {
-// showFragment(VerificationQrScannedByOtherFragment::class)
-// return@withState
-// }
-// //TODO
-// // is VerificationTxState.Started,
-// is VerificationTxState.WaitingOtherReciprocateConfirm -> {
-// showFragment(
-// VerificationQRWaitingFragment::class,
-// VerificationQRWaitingFragment.Args(
-// isMe = state.isMe,
-// otherUserName = state.otherUserMxItem.getBestName()
-// )
-// )
-// return@withState
-// }
-// is VerificationTxState.Verified -> {
-// showFragment(
-// VerificationConclusionFragment::class,
-// VerificationConclusionFragment.Args(true, null, state.isMe)
-// )
-// return@withState
-// }
-// is VerificationTxState.Cancelled -> {
-// showFragment(
-// VerificationConclusionFragment::class,
-// VerificationConclusionFragment.Args(false, state.qrTransactionState.cancelCode.value, state.isMe)
-// )
-// return@withState
-// }
-// else -> Unit
-// }
-//
-// // At this point there is no SAS transaction for this request
-//
-// // Transaction has not yet started
-// if (state.pendingRequest.invoke()?.cancelConclusion != null) {
-// // The request has been declined, we should dismiss
-// views.otherUserNameText.text = getString(R.string.verification_cancelled)
-// showFragment(
-// VerificationConclusionFragment::class,
-// VerificationConclusionFragment.Args(
-// isSuccessFull = false,
-// cancelReason = state.pendingRequest.invoke()?.cancelConclusion?.value ?: CancelCode.User.value,
-// isMe = state.isMe
-// )
-// )
-// return@withState
-// }
-//
-// // If it's an outgoing
-// if (state.pendingRequest.invoke() == null || state.pendingRequest.invoke()?.isIncoming == false || state.selfVerificationMode) {
-// Timber.v("## SAS show bottom sheet for outgoing request")
-// if (state.pendingRequest.invoke()?.state == EVerificationState.Ready) {
-// Timber.v("## SAS show bottom sheet for outgoing and ready request")
-// // Show choose method fragment with waiting
-// showFragment(
-// VerificationChooseMethodFragment::class,
-// VerificationArgs(
-// otherUserId = state.otherUserId,
-// verificationId = state.pendingRequest.invoke()?.transactionId
-// )
-// )
-// } else {
-// // Stay on the start fragment
-// showFragment(
-// VerificationRequestFragment::class,
-// VerificationArgs(
-// otherUserId = state.otherUserId,
-// verificationId = state.pendingRequest.invoke()?.transactionId,
-// )
-// )
-// }
-// } else if (state.pendingRequest.invoke()?.isIncoming == true) {
-// Timber.v("## SAS show bottom sheet for Incoming request")
-// // For incoming we can switch to choose method because ready is being sent or already sent
-// showFragment(
-// VerificationChooseMethodFragment::class,
-// VerificationArgs(
-// otherUserId = state.otherUserId,
-// verificationId = state.pendingRequest.invoke()?.transactionId
-// )
-// )
-// }
-// super.invalidate()
-// }
-//
-// private fun showFragment(fragmentClass: KClass, argsParcelable: Parcelable? = null) {
-// if (childFragmentManager.findFragmentByTag(fragmentClass.simpleName) == null) {
-// childFragmentManager.commitTransaction {
-// replace(
-// R.id.bottomSheetFragmentContainer,
-// fragmentClass.java,
-// argsParcelable?.toMvRxBundle(),
-// fragmentClass.simpleName
-// )
-// }
-// }
-// }
-//
-// companion object {
-// fun withArgs(otherUserId: String, transactionId: String): VerificationBottomSheet {
-// return VerificationBottomSheet().apply {
-// setArguments(
-// VerificationArgs(
-// otherUserId = otherUserId,
-// verificationId = transactionId,
-// )
-// )
-// }
-// }
-//
-// // fun forSelfVerification(session: Session): VerificationBottomSheet {
-// // return VerificationBottomSheet().apply {
-// // setArguments(
-// // VerificationArgs(
-// // otherUserId = session.myUserId,
-// // selfVerificationMode = true
-// // )
-// // )
-// // }
-// // }
-//
-// // fun forSelfVerification(session: Session, outgoingRequest: String): VerificationBottomSheet {
-// // return VerificationBottomSheet().apply {
-// // setArguments(
-// // VerificationArgs(
-// // otherUserId = session.myUserId,
-// // selfVerificationMode = true,
-// // verificationId = outgoingRequest
-// // )
-// // )
-// // }
-// // }
-//
-// // const val WAITING_SELF_VERIF_TAG: String = "WAITING_SELF_VERIF_TAG"
-// }
-// }
-//
-// // fun View.getParentCoordinatorLayout(): CoordinatorLayout? {
-// // var current = this as? View
-// // while (current != null) {
-// // if (current is CoordinatorLayout) return current
-// // current = current.parent as? View
-// // }
-// // return null
-// // }
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewEvents.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewEvents.kt
index e52fb0e2cd..488c4ab487 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewEvents.kt
@@ -27,6 +27,7 @@ sealed class VerificationBottomSheetViewEvents : VectorViewEvents {
object AccessSecretStore : VerificationBottomSheetViewEvents()
object ResetAll : VerificationBottomSheetViewEvents()
object GoToSettings : VerificationBottomSheetViewEvents()
+ data class ConfirmCancel(val otherUserId: String, val deviceId: String?) : VerificationBottomSheetViewEvents()
data class ModalError(val errorMessage: CharSequence) : VerificationBottomSheetViewEvents()
data class RequestNotFound(val transactionId: String) : VerificationBottomSheetViewEvents()
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt
deleted file mode 100644
index 61e70265a4..0000000000
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt
+++ /dev/null
@@ -1,665 +0,0 @@
-// /*
-// * Copyright 2019 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 com.airbnb.mvrx.Async
-// import com.airbnb.mvrx.Fail
-// import com.airbnb.mvrx.Loading
-// import com.airbnb.mvrx.MavericksState
-// import com.airbnb.mvrx.MavericksViewModelFactory
-// import com.airbnb.mvrx.Success
-// import com.airbnb.mvrx.Uninitialized
-// import dagger.assisted.Assisted
-// import dagger.assisted.AssistedFactory
-// import dagger.assisted.AssistedInject
-// import im.vector.app.R
-// import im.vector.app.core.di.MavericksAssistedViewModelFactory
-// import im.vector.app.core.di.hiltMavericksViewModelFactory
-// import im.vector.app.core.platform.VectorViewModel
-// import im.vector.app.core.resources.StringProvider
-// import im.vector.app.features.raw.wellknown.getElementWellknown
-// import im.vector.app.features.raw.wellknown.isSecureBackupRequired
-// import im.vector.app.features.session.coroutineScope
-// import kotlinx.coroutines.Dispatchers
-// import kotlinx.coroutines.flow.collect
-// import kotlinx.coroutines.flow.filter
-// import kotlinx.coroutines.flow.launchIn
-// import kotlinx.coroutines.flow.onEach
-// import kotlinx.coroutines.launch
-// import org.matrix.android.sdk.api.Matrix
-// import org.matrix.android.sdk.api.extensions.orFalse
-// import org.matrix.android.sdk.api.extensions.tryOrNull
-// import org.matrix.android.sdk.api.raw.RawService
-// import org.matrix.android.sdk.api.session.Session
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
-// import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
-// import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupUtils
-// import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey
-// import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
-// import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
-// import org.matrix.android.sdk.api.session.crypto.verification.IVerificationRequest
-// import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
-// import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerificationTransaction
-// import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
-// import org.matrix.android.sdk.api.session.crypto.verification.VerificationEvent
-// import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
-// import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
-// import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
-// import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
-// import org.matrix.android.sdk.api.session.events.model.LocalEcho
-// import org.matrix.android.sdk.api.session.getUser
-// import org.matrix.android.sdk.api.util.MatrixItem
-// import org.matrix.android.sdk.api.util.fromBase64
-// import org.matrix.android.sdk.api.util.toMatrixItem
-// import timber.log.Timber
-//
-// data class VerificationBottomSheetViewState(
-// val otherUserId: String,
-// val verificationId: String?,
-// val roomId: String?,
-// // true when we display the loading and we wait for the other (incoming request)
-// val selfVerificationMode: Boolean,
-// val otherUserMxItem: MatrixItem,
-// val pendingRequest: Async = Uninitialized,
-// val pendingLocalId: String? = null,
-// val sasTransactionState: VerificationTxState? = null,
-// val qrTransactionState: VerificationTxState? = null,
-// val transactionId: String? = null,
-// val verifiedFromPrivateKeys: Boolean = false,
-// val verifyingFrom4S: Boolean = false,
-// val isMe: Boolean = false,
-// val currentDeviceCanCrossSign: Boolean = false,
-// val userWantsToCancel: Boolean = false,
-// val userThinkItsNotHim: Boolean = false,
-// val quadSContainsSecrets: Boolean = true,
-// val isVerificationRequired: Boolean = false,
-// val quadSHasBeenReset: Boolean = false,
-// val hasAnyOtherSession: Boolean = false
-// ) : MavericksState {
-//
-// constructor(args: VerificationBottomSheet.VerificationArgs) : this(
-// otherUserId = args.otherUserId,
-// verificationId = args.verificationId,
-// selfVerificationMode = args.selfVerificationMode,
-// roomId = args.roomId,
-// otherUserMxItem = MatrixItem.UserItem(args.otherUserId),
-// )
-// }
-//
-// class VerificationBottomSheetViewModel @AssistedInject constructor(
-// @Assisted initialState: VerificationBottomSheetViewState,
-// private val rawService: RawService,
-// private val session: Session,
-// private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider,
-// private val stringProvider: StringProvider,
-// private val matrix: Matrix,
-// ) :
-// VectorViewModel(initialState),
-// VerificationService.Listener {
-//
-// @AssistedFactory
-// interface Factory : MavericksAssistedViewModelFactory {
-// override fun create(initialState: VerificationBottomSheetViewState): VerificationBottomSheetViewModel
-// }
-//
-// companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory()
-//
-// init {
-// // session.cryptoService().verificationService().addListener(this)
-//
-// // This is async, but at this point should be in cache
-// // so it's ok to not wait until result
-// viewModelScope.launch(Dispatchers.IO) {
-// val wellKnown = rawService.getElementWellknown(session.sessionParams)
-// setState {
-// copy(isVerificationRequired = wellKnown?.isSecureBackupRequired().orFalse())
-// }
-// }
-//
-//
-// // viewModelScope.launch {
-// //
-// // var autoReady = false
-// // val pr = if (initialState.selfVerificationMode) {
-// // // See if active tx for this user and take it
-// //
-// // session.cryptoService().verificationService().getExistingVerificationRequests(initialState.otherUserId)
-// // .lastOrNull { !it.isFinished }
-// // ?.also { verificationRequest ->
-// // if (verificationRequest.isIncoming && !verificationRequest.isReady) {
-// // // auto ready in this case, as we are waiting
-// // autoReady = true
-// // }
-// // }
-// // } else {
-// // session.cryptoService().verificationService().getExistingVerificationRequest(initialState.otherUserId, initialState.transactionId)
-// // }
-// //
-// // val sasTx = (pr?.transactionId ?: initialState.transactionId)?.let {
-// // session.cryptoService().verificationService().getExistingTransaction(initialState.otherUserId, it) as? SasVerificationTransaction
-// // }
-// //
-// // val qrTx = (pr?.transactionId ?: initialState.transactionId)?.let {
-// // session.cryptoService().verificationService().getExistingTransaction(initialState.otherUserId, it) as? QrCodeVerificationTransaction
-// // }
-// //
-// // setState {
-// // copy(
-// // sasTransactionState = sasTx?.state,
-// // qrTransactionState = qrTx?.state,
-// // transactionId = pr?.transactionId ?: initialState.transactionId,
-// // pendingRequest = if (pr != null) Success(pr) else Uninitialized,
-// // isMe = initialState.otherUserId == session.myUserId,
-// // currentDeviceCanCrossSign = session.cryptoService().crossSigningService().canCrossSign(),
-// // quadSContainsSecrets = session.sharedSecretStorageService().isRecoverySetup(),
-// // hasAnyOtherSession = hasAnyOtherSession
-// // )
-// // }
-// //
-// // if (autoReady) {
-// // // TODO, can I be here in DM mode? in this case should test if roomID is null?
-// // session.cryptoService().verificationService()
-// // .readyPendingVerification(
-// // supportedVerificationMethodsProvider.provide(),
-// // pr!!.otherUserId,
-// // pr.transactionId ?: ""
-// // )
-// // }
-// // }
-// }
-//
-// private fun fetchOtherUserProfile(otherUserId: String) {
-// session.getUser(otherUserId)?.toMatrixItem()?.let {
-// setState {
-// copy(
-// otherUserMxItem = it
-// )
-// }
-// }
-// // Always fetch the latest User data
-// viewModelScope.launch {
-// tryOrNull { session.userService().resolveUser(otherUserId) }
-// ?.toMatrixItem()
-// ?.let {
-// setState {
-// copy(
-// otherUserMxItem = it
-// )
-// }
-// }
-// }
-// }
-//
-// // override fun onCleared() {
-// // super.onCleared()
-// // }
-//
-// fun queryCancel() = withState { state ->
-// if (state.userThinkItsNotHim) {
-// setState {
-// copy(userThinkItsNotHim = false)
-// }
-// } else {
-// // if the verification is already done you can't cancel anymore
-// if (state.pendingRequest.invoke()?.cancelConclusion != null ||
-// // state.sasTransactionState is VerificationTxState.TerminalTxState ||
-// state.verifyingFrom4S) {
-// // you cannot cancel anymore
-// } else {
-// if (!state.isVerificationRequired) {
-// setState {
-// copy(userWantsToCancel = true)
-// }
-// }
-// }
-// }
-// }
-//
-// fun confirmCancel() = withState { state ->
-// cancelAllPendingVerifications(state)
-// _viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
-// }
-//
-// private fun cancelAllPendingVerifications(state: VerificationBottomSheetViewState) {
-// viewModelScope.launch {
-// session.cryptoService()
-// .verificationService().getExistingVerificationRequest(state.otherUserId, state.transactionId)?.let {
-// session.cryptoService().verificationService().cancelVerificationRequest(it)
-// }
-// session.cryptoService()
-// .verificationService()
-// .getExistingTransaction(state.otherUserId, state.transactionId ?: "")
-// ?.cancel(CancelCode.User)
-// }
-// }
-//
-// fun continueFromCancel() {
-// setState {
-// copy(userWantsToCancel = false)
-// }
-// }
-//
-// fun continueFromWasNotMe() {
-// setState {
-// copy(userThinkItsNotHim = false)
-// }
-// }
-//
-// fun itWasNotMe() {
-// setState {
-// copy(userThinkItsNotHim = true)
-// }
-// }
-//
-// fun goToSettings() = withState { state ->
-// cancelAllPendingVerifications(state)
-// _viewEvents.post(VerificationBottomSheetViewEvents.GoToSettings)
-// }
-//
-// override fun handle(action: VerificationAction) = withState { state ->
-// val otherUserId = state.otherUserId
-// val roomId = state.roomId
-// ?: session.roomService().getExistingDirectRoomWithUser(otherUserId)
-//
-// when (action) {
-// is VerificationAction.RequestVerificationByDM -> {
-// setState {
-// copy(
-// pendingRequest = Loading()
-// )
-// }
-//
-// if (roomId == null) {
-// // val localId = LocalEcho.createLocalEchoId()
-// session.coroutineScope.launch {
-// try {
-// val roomId = session.roomService().createDirectRoom(otherUserId)
-// val request = session
-// .cryptoService()
-// .verificationService()
-// .requestKeyVerificationInDMs(
-// supportedVerificationMethodsProvider.provide(),
-// otherUserId,
-// roomId,
-// )
-// setState {
-// copy(
-// roomId = roomId,
-// pendingRequest = Success(request),
-// transactionId = request.transactionId
-// )
-// }
-// } catch (failure: Throwable) {
-// setState {
-// copy(pendingRequest = Fail(failure))
-// }
-// }
-// }
-// } else {
-// session.coroutineScope.launch {
-// val request = session
-// .cryptoService()
-// .verificationService()
-// .requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), otherUserId, roomId)
-// setState {
-// copy(
-// pendingRequest = Success(request),
-// transactionId = request.transactionId
-// )
-// }
-// }
-// }
-// Unit
-// }
-// is VerificationAction.StartSASVerification -> {
-// viewModelScope.launch {
-// val request = session.cryptoService().verificationService().getExistingVerificationRequest(otherUserId, state.transactionId)
-// ?: return@launch
-// val otherDevice = request.otherDeviceId
-// if (roomId == null) {
-// session.cryptoService().verificationService().requestSelfKeyVerification(
-// listOf(VerificationMethod.SAS)
-// )
-// } else {
-// session.cryptoService().verificationService().requestKeyVerificationInDMs(
-// listOf(VerificationMethod.SAS),
-// roomId = roomId,
-// otherUserId = request.otherUserId,
-// )
-// }
-// }
-// Unit
-// }
-// is VerificationAction.RemoteQrCodeScanned -> {
-// viewModelScope.launch {
-// val existingTransaction = session.cryptoService().verificationService()
-// .getExistingTransaction(action.otherUserId, action.transactionId) as? QrCodeVerificationTransaction
-// existingTransaction
-// ?.userHasScannedOtherQrCode(action.scannedData)
-// }
-// }
-// is VerificationAction.OtherUserScannedSuccessfully -> {
-// viewModelScope.launch {
-// val transactionId = state.transactionId ?: return@launch
-//
-// val existingTransaction = session.cryptoService().verificationService()
-// .getExistingTransaction(otherUserId, transactionId) as? QrCodeVerificationTransaction
-// existingTransaction
-// ?.otherUserScannedMyQrCode()
-// }
-// }
-// is VerificationAction.OtherUserDidNotScanned -> {
-// val transactionId = state.transactionId ?: return@withState
-// viewModelScope.launch {
-// val existingTransaction = session.cryptoService().verificationService()
-// .getExistingTransaction(otherUserId, transactionId) as? QrCodeVerificationTransaction
-// existingTransaction
-// ?.otherUserDidNotScannedMyQrCode()
-// }
-// }
-// is VerificationAction.SASMatchAction -> {
-// val request = state.pendingRequest.invoke() ?: return@withState
-// viewModelScope.launch {
-// (session.cryptoService().verificationService()
-// .getExistingTransaction(request.otherUserId, request.transactionId)
-// as? SasVerificationTransaction)?.userHasVerifiedShortCode()
-// }
-// }
-// is VerificationAction.SASDoNotMatchAction -> {
-// val request = state.pendingRequest.invoke() ?: return@withState
-// viewModelScope.launch {
-// (session.cryptoService().verificationService()
-// .getExistingTransaction(request.otherUserId, request.transactionId)
-// as? SasVerificationTransaction)
-// ?.shortCodeDoesNotMatch()
-// }
-// }
-// is VerificationAction.ReadyPendingVerification -> {
-// state.pendingRequest.invoke()?.let { request ->
-// // will only be there for dm verif
-// session.coroutineScope.launch {
-// if (state.roomId != null) {
-// session.cryptoService().verificationService()
-// .readyPendingVerification(
-// supportedVerificationMethodsProvider.provide(),
-// state.otherUserId,
-// request.transactionId
-// )
-// }
-// }
-// }
-// }
-// is VerificationAction.CancelPendingVerification -> {
-// state.pendingRequest.invoke()?.let {
-// session.coroutineScope.launch {
-// session.cryptoService().verificationService()
-// .cancelVerificationRequest(it)
-// }
-// }
-// _viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
-// }
-// is VerificationAction.GotItConclusion -> {
-// if (state.isVerificationRequired && !action.verified) {
-// // we should go back to first screen
-// setState {
-// copy(
-// pendingRequest = Uninitialized,
-// // sasTransactionState = null,
-// // qrTransactionState = null
-// )
-// }
-// } else {
-// _viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
-// }
-// }
-// is VerificationAction.SkipVerification -> {
-// _viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
-// }
-// is VerificationAction.VerifyFromPassphrase -> {
-// setState { copy(verifyingFrom4S = true) }
-// _viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore)
-// }
-// is VerificationAction.GotResultFromSsss -> {
-// handleSecretBackFromSSSS(action)
-// }
-// VerificationAction.SecuredStorageHasBeenReset -> {
-// if (session.cryptoService().crossSigningService().allPrivateKeysKnown()) {
-// setState {
-// copy(quadSHasBeenReset = true, verifyingFrom4S = false)
-// }
-// }
-// Unit
-// }
-// VerificationAction.CancelledFromSsss -> {
-// setState {
-// copy(verifyingFrom4S = false)
-// }
-// }
-// }
-// }
-//
-// private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
-// viewModelScope.launch(Dispatchers.IO) {
-// try {
-// action.cypherData.fromBase64().inputStream().use { ins ->
-// val res = matrix.secureStorageService().loadSecureSecret