From 5c82bdba381cec670232839aa2b53576d1c83359 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 17 Nov 2022 22:42:47 +0100 Subject: [PATCH] happy path qr kotlin verif --- .../android/sdk/common/CryptoTestHelper.kt | 1 - .../internal/crypto/verification/SASTest.kt | 1 - .../DefaultVerificationService.kt | 4 +- .../verification/KotlinQRVerification.kt | 56 +- ...Transaction.kt => KotlinSasTransaction.kt} | 8 +- .../crypto/verification/VerificationActor.kt | 504 +++++-- .../crypto/verification/VerificationIntent.kt | 7 +- .../VerificationMessageProcessor.kt | 4 +- .../verification/IVerificationRequest.kt | 14 +- .../PendingVerificationRequest.kt | 10 +- .../QrCodeVerificationTransaction.kt | 18 +- .../SasVerificationTransaction.kt | 4 + .../crypto/verification/VerificationEvent.kt | 9 +- .../verification/VerificationTransaction.kt | 4 +- .../verification/VerificationTxState.kt | 79 +- .../VerificationListenersHolder.kt | 1 - .../app/core/di/MavericksViewModelModule.kt | 25 +- .../crypto/keysrequest/KeyRequestHandler.kt | 7 +- .../IncomingVerificationRequestHandler.kt | 18 +- .../verification/VerificationBottomSheet.kt | 818 +++++------ .../VerificationBottomSheetViewModel.kt | 1290 ++++++++--------- .../cancel/VerificationCancelController.kt | 218 +-- .../cancel/VerificationCancelFragment.kt | 146 +- .../cancel/VerificationNotMeController.kt | 168 +-- .../cancel/VerificationNotMeFragment.kt | 146 +- .../VerificationChooseMethodController.kt | 294 ++-- .../VerificationChooseMethodFragment.kt | 272 ++-- .../VerificationChooseMethodViewModel.kt | 336 ++--- .../VerificationConclusionController.kt | 286 ++-- .../VerificationConclusionFragment.kt | 164 +-- .../VerificationConclusionViewModel.kt | 136 +- .../emoji/VerificationEmojiCodeController.kt | 336 ++--- .../emoji/VerificationEmojiCodeFragment.kt | 162 +-- .../emoji/VerificationEmojiCodeViewModel.kt | 416 +++--- .../VerificationQrScannedByOtherController.kt | 198 +-- .../VerificationQrScannedByOtherFragment.kt | 146 +- .../request/VerificationRequestController.kt | 370 ++--- .../request/VerificationRequestFragment.kt | 170 +-- .../VerificationTransactionController.kt | 356 ++--- .../VerificationTransactionFragment.kt | 72 +- .../user/UserVerificationBottomSheet.kt | 8 - .../user/UserVerificationController.kt | 131 +- .../user/UserVerificationFragment.kt | 8 + .../user/UserVerificationViewModel.kt | 145 +- .../vector/app/features/home/HomeActivity.kt | 2 +- .../home/room/detail/TimelineFragment.kt | 1 - .../features/navigation/DefaultNavigator.kt | 1 - .../RoomMemberProfileFragment.kt | 1 - .../devices/DeviceListBottomSheet.kt | 12 +- .../settings/devices/DevicesViewModel.kt | 5 +- .../devices/VectorSettingsDevicesFragment.kt | 12 +- .../devices/v2/VectorSessionsListViewModel.kt | 4 +- .../v2/VectorSettingsDevicesFragment.kt | 12 +- 53 files changed, 4009 insertions(+), 3607 deletions(-) rename matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/{SasV1Transaction.kt => KotlinSasTransaction.kt} (99%) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt index 8c4a0d35af..170df3c1f4 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt @@ -40,7 +40,6 @@ import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.getRoom diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt index 0e38e8e86f..73833116f8 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt @@ -561,7 +561,6 @@ class SASTest : InstrumentedTest { val requestID = req.transactionId - Log.v("TEST", "== requestID is $requestID") testHelper.retryPeriodically { diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt index 512d37d0e2..b5a3919eb9 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt @@ -1233,7 +1233,7 @@ internal class DefaultVerificationService @Inject constructor( } override suspend fun reciprocateQRVerification(otherUserId: String, requestId: String, scannedData: String): String? { - val deferred = CompletableDeferred() + val deferred = CompletableDeferred() stateMachine.send( VerificationIntent.ActionReciprocateQrVerification( otherUserId = otherUserId, @@ -1242,7 +1242,7 @@ internal class DefaultVerificationService @Inject constructor( deferred = deferred ) ) - return deferred.await().transactionId + return deferred.await()?.transactionId } override suspend fun requestKeyVerificationInDMs( diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/KotlinQRVerification.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/KotlinQRVerification.kt index 7ae2b26ed3..9b8b5f2c23 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/KotlinQRVerification.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/KotlinQRVerification.kt @@ -16,41 +16,67 @@ package org.matrix.android.sdk.internal.crypto.verification +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.channels.Channel import org.matrix.android.sdk.api.session.crypto.verification.CancelCode +import org.matrix.android.sdk.api.session.crypto.verification.QRCodeVerificationState import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState +import org.matrix.android.sdk.internal.crypto.verification.qrcode.QrCodeData +import org.matrix.android.sdk.internal.crypto.verification.qrcode.toEncodedString -class KotlinQRVerification( - override val qrCodeText: String?, - override val state: VerificationTxState, +internal class KotlinQRVerification( + private val channel: Channel, + var qrCodeData: QrCodeData?, override val method: VerificationMethod, override val transactionId: String, override val otherUserId: String, override val otherDeviceId: String?, - override val isIncoming: Boolean) : QrCodeVerificationTransaction { + override val isIncoming: Boolean, + var state: QRCodeVerificationState, + val isToDevice: Boolean +) : QrCodeVerificationTransaction { - override suspend fun userHasScannedOtherQrCode(otherQrCodeText: String) { - TODO("Not yet implemented") - } + override fun state() = state + + override val qrCodeText: String? + get() = qrCodeData?.toEncodedString() +// +// var userMSKKeyToTrust: String? = null +// var deviceKeysToTrust = mutableListOf() + +// override suspend fun userHasScannedOtherQrCode(otherQrCodeText: String) { +// TODO("Not yet implemented") +// } override suspend fun otherUserScannedMyQrCode() { - TODO("Not yet implemented") + val deferred = CompletableDeferred() + channel.send( + VerificationIntent.ActionConfirmCodeWasScanned(otherUserId, transactionId, deferred) + ) + deferred.await() } override suspend fun otherUserDidNotScannedMyQrCode() { - TODO("Not yet implemented") + val deferred = CompletableDeferred() + channel.send( + // TODO what cancel code?? + VerificationIntent.ActionCancel(transactionId, deferred) + ) + deferred.await() } override suspend fun cancel() { - TODO("Not yet implemented") + cancel(CancelCode.User) } override suspend fun cancel(code: CancelCode) { - TODO("Not yet implemented") + val deferred = CompletableDeferred() + channel.send( + VerificationIntent.ActionCancel(transactionId, deferred) + ) + deferred.await() } - override fun isToDeviceTransport(): Boolean { - TODO("Not yet implemented") - } + override fun isToDeviceTransport() = isToDevice } diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/SasV1Transaction.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/KotlinSasTransaction.kt similarity index 99% rename from matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/SasV1Transaction.kt rename to matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/KotlinSasTransaction.kt index c303ab6fb7..f9b9b6a1bc 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/SasV1Transaction.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/KotlinSasTransaction.kt @@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation import org.matrix.android.sdk.api.session.crypto.verification.SasMode +import org.matrix.android.sdk.api.session.crypto.verification.SasTransactionState import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction.Companion.KEY_AGREEMENT_V1 import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction.Companion.KEY_AGREEMENT_V2 @@ -32,7 +33,6 @@ import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTra import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction.Companion.SAS_MAC_SHA256 import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction.Companion.SAS_MAC_SHA256_LONGKDF import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.RelationType import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationAcceptContent import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationKeyContent @@ -50,9 +50,8 @@ import org.matrix.olm.OlmSAS import timber.log.Timber import java.util.Locale -internal class SasV1Transaction( +internal class KotlinSasTransaction( private val channel: Channel, - override var state: VerificationTxState, override val transactionId: String, override val otherUserId: String, private val myUserId: String, @@ -63,6 +62,7 @@ internal class SasV1Transaction( override val isIncoming: Boolean, val startReq: ValidVerificationInfoStart.SasVerificationInfoStart? = null, val isToDevice: Boolean, + var state: SasTransactionState ) : SasVerificationTransaction { override val method: VerificationMethod @@ -207,6 +207,8 @@ internal class SasV1Transaction( var myMac: ValidVerificationInfoMac? = null var theirMac: ValidVerificationInfoMac? = null + override fun state() = this.state + override fun supportsEmoji(): Boolean { return accepted?.shortAuthenticationStrings?.contains(SasMode.EMOJI) == true } diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationActor.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationActor.kt index 6cde13dcc7..35dab90524 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationActor.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationActor.kt @@ -27,19 +27,23 @@ import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +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.MXUsersDevicesMap import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject 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.PendingVerificationRequest -import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerificationTransaction +import org.matrix.android.sdk.api.session.crypto.verification.QRCodeVerificationState +import org.matrix.android.sdk.api.session.crypto.verification.SasTransactionState import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoReady import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoRequest 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.VerificationTransaction -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event @@ -53,6 +57,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVerification import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationStartContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent +import org.matrix.android.sdk.internal.crypto.SecretShareManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationDone @@ -94,7 +99,8 @@ internal class VerificationActor @AssistedInject constructor( private val localEchoEventFactory: LocalEchoEventFactory, private val sendToDeviceTask: SendToDeviceTask, private val setDeviceVerificationAction: SetDeviceVerificationAction, - private val crossSigningService: dagger.Lazy + private val crossSigningService: dagger.Lazy, + private val secretShareManager: SecretShareManager, ) { @AssistedFactory @@ -121,6 +127,34 @@ internal class VerificationActor @AssistedInject constructor( channel.send(intent) } + private suspend fun withMatchingRequest( + otherUserId: String, + requestId: String, + block: suspend ((KotlinVerificationRequest) -> Unit) + ) { + val matchingRequest = pendingRequests[otherUserId] + ?.firstOrNull { it.requestId == requestId } + ?: return Unit.also { + // Receive a transaction event with no matching request.. should ignore. + // Not supported any more to do raw start + Timber.tag(loggerTag.value) + .v("[${myUserId.take(8)}] request $requestId not found!") + } + + if (matchingRequest.state == EVerificationState.HandledByOtherSession) { + Timber.tag(loggerTag.value) + .v("[${myUserId.take(8)}] ignore transaction event for $requestId handled by other") + return + } + + if (matchingRequest.isFinished()) { + Timber.tag(loggerTag.value) + .v("[${myUserId.take(8)}] ignore transaction event for $requestId for finished request") + return + } + block.invoke(matchingRequest) + } + private suspend fun withMatchingRequest( otherUserId: String, requestId: String, @@ -202,7 +236,13 @@ internal class VerificationActor @AssistedInject constructor( handleSasStart(msg) } is VerificationIntent.ActionReciprocateQrVerification -> { - handleReciprocateQR(msg) + handleActionReciprocateQR(msg) + } + is VerificationIntent.ActionConfirmCodeWasScanned -> { + withMatchingRequest(msg.otherUserId, msg.requestId) { + handleActionQRScanConfirmed(it) + } + msg.deferred.complete(Unit) } is VerificationIntent.OnStartReceived -> { onStartReceived(msg) @@ -277,14 +317,15 @@ internal class VerificationActor @AssistedInject constructor( request.state = EVerificationState.Cancelled val cancelCode = safeValueOf(msg.validCancel.code) request.cancelCode = cancelCode - val existingTx = txMap[msg.fromUser]?.get(msg.validCancel.transactionId) + // TODO or QR + val existingTx: KotlinSasTransaction? = + getExistingTransaction(msg.validCancel.transactionId) // txMap[msg.fromUser]?.get(msg.validCancel.transactionId) if (existingTx != null) { - existingTx.state = VerificationTxState.Cancelled(cancelCode, false) + existingTx.state = SasTransactionState.Cancelled(cancelCode, false) txMap[msg.fromUser]?.remove(msg.validCancel.transactionId) eventFlow.emit(VerificationEvent.TransactionUpdated(existingTx)) } eventFlow.emit(VerificationEvent.RequestUpdated(request.toPendingVerificationRequest())) - } } is VerificationIntent.OnReadyByAnotherOfMySessionReceived -> { @@ -358,6 +399,27 @@ internal class VerificationActor @AssistedInject constructor( } private suspend fun handleReceiveStartForQR(request: KotlinVerificationRequest, reciprocate: ValidVerificationInfoStart.ReciprocateVerificationInfoStart) { + // Ok so the other did scan our code + val ourSecret = request.qrCodeData?.sharedSecret + if (ourSecret != reciprocate.sharedSecret) { + // something went wrong + cancelRequest(request, CancelCode.MismatchedKeys) + return + } + + // The secret matches, we need manual action to confirm that it was scan + val tx = KotlinQRVerification( + channel = this.channel, + state = QRCodeVerificationState.WaitingForScanConfirmation, + qrCodeData = request.qrCodeData, + method = VerificationMethod.QR_CODE_SCAN, + transactionId = request.requestId, + otherUserId = request.otherUserId, + otherDeviceId = request.otherDeviceId(), + isIncoming = false, + isToDevice = request.roomId == null + ) + addTransaction(tx) } private suspend fun handleReceiveStartForSas( @@ -372,7 +434,7 @@ internal class VerificationActor @AssistedInject constructor( // and the other m.key.verification.start event is ignored. // So let's check if I already send a start? val requestId = msg.validVerificationInfoStart.transactionId - val existing = getExistingTransaction(msg.fromUser, requestId) + val existing: KotlinSasTransaction? = getExistingTransaction(msg.fromUser, requestId) if (existing != null) { Timber.tag(loggerTag.value) .v("[${myUserId.take(8)}] No existing Sas transaction for ${request.requestId}") @@ -380,23 +442,6 @@ internal class VerificationActor @AssistedInject constructor( return } - val sasTx = SasV1Transaction( - channel = channel, - transactionId = requestId, - state = VerificationTxState.None, - otherUserId = request.otherUserId, - myUserId = myUserId, - myTrustedMSK = cryptoStore.getMyCrossSigningInfo() - ?.takeIf { it.isTrusted() } - ?.masterKey() - ?.unpaddedBase64PublicKey, - otherDeviceId = request.otherDeviceId(), - myDeviceId = cryptoStore.getDeviceId(), - myDeviceFingerprint = cryptoStore.getUserDevice(myUserId, cryptoStore.getDeviceId())?.fingerprint().orEmpty(), - startReq = sasStart, - isIncoming = true, - isToDevice = msg.viaRoom == null - ) // we accept with the agreement methods // Select a key agreement protocol, a hash algorithm, a message authentication code, // and short authentication string methods out of the lists given in requester's message. @@ -440,11 +485,28 @@ internal class VerificationActor @AssistedInject constructor( cancelRequest(request, CancelCode.UserError) return } + val sasTx = KotlinSasTransaction( + channel = channel, + transactionId = requestId, + state = SasTransactionState.None, + otherUserId = request.otherUserId, + myUserId = myUserId, + myTrustedMSK = cryptoStore.getMyCrossSigningInfo() + ?.takeIf { it.isTrusted() } + ?.masterKey() + ?.unpaddedBase64PublicKey, + otherDeviceId = request.otherDeviceId(), + myDeviceId = cryptoStore.getDeviceId(), + myDeviceFingerprint = cryptoStore.getUserDevice(myUserId, cryptoStore.getDeviceId())?.fingerprint().orEmpty(), + startReq = sasStart, + isIncoming = true, + isToDevice = msg.viaRoom == null, + ) val concat = sasTx.getSAS().publicKey + sasStart.canonicalJson val commitment = hashUsingAgreedHashMethod(agreedHash, concat) - val accept = SasV1Transaction.sasAccept( + val accept = KotlinSasTransaction.sasAccept( inRoom = request.roomId != null, requestId = requestId, keyAgreementProtocol = agreedProtocol, @@ -464,7 +526,6 @@ internal class VerificationActor @AssistedInject constructor( } sasTx.accepted = accept.asValidObject() - sasTx.state = VerificationTxState.SasAccepted addTransaction(sasTx) } @@ -472,13 +533,13 @@ internal class VerificationActor @AssistedInject constructor( private suspend fun handleReceiveAccept(matchingRequest: KotlinVerificationRequest, msg: VerificationIntent.OnAcceptReceived) { val requestId = msg.validAccept.transactionId - val existing = getExistingTransaction(msg.fromUser, requestId) + val existing: KotlinSasTransaction = getExistingTransaction(msg.fromUser, requestId) ?: return Unit.also { Timber.v("on accept received in room ${msg.viaRoom} for verification id:${requestId} in room ${matchingRequest.roomId}") } // Existing should be in - if (existing.state != VerificationTxState.SasStarted) { + if (existing.state != SasTransactionState.SasStarted) { // it's a wrong state should cancel? // TODO cancel } @@ -501,10 +562,9 @@ internal class VerificationActor @AssistedInject constructor( // and replies with a to_device message with type set to “m.key.verification.key”, sending Alice’s public key QA val pubKey = existing.getSAS().publicKey - val keyMessage = SasV1Transaction.sasKeyMessage(matchingRequest.roomId != null, requestId, pubKey) + val keyMessage = KotlinSasTransaction.sasKeyMessage(matchingRequest.roomId != null, requestId, pubKey) try { - if (BuildConfig.LOG_PRIVATE_DATA) { Timber.tag(loggerTag.value) .v("[${myUserId.take(8)}]: Sending my key $pubKey") @@ -515,7 +575,7 @@ internal class VerificationActor @AssistedInject constructor( keyMessage, ) } catch (failure: Throwable) { - existing.state = VerificationTxState.Cancelled(CancelCode.UserError, true) + existing.state = SasTransactionState.Cancelled(CancelCode.UserError, true) matchingRequest.cancelCode = CancelCode.UserError matchingRequest.state = EVerificationState.Cancelled eventFlow.emit(VerificationEvent.RequestUpdated(matchingRequest.toPendingVerificationRequest())) @@ -523,7 +583,7 @@ internal class VerificationActor @AssistedInject constructor( return } existing.accepted = accept - existing.state = VerificationTxState.SasKeySent + existing.state = SasTransactionState.SasKeySent eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) } @@ -545,13 +605,13 @@ internal class VerificationActor @AssistedInject constructor( msg.deferred.completeExceptionally(java.lang.IllegalArgumentException("Failed to find other device Id")) } - val existingTransaction = getExistingTransaction(msg.otherUserId, msg.requestId) + val existingTransaction = getExistingTransaction(msg.otherUserId, msg.requestId) if (existingTransaction is SasVerificationTransaction) { // there is already an existing transaction?? msg.deferred.completeExceptionally(IllegalStateException("Already started")) return } - val startMessage = SasV1Transaction.sasStart( + val startMessage = KotlinSasTransaction.sasStart( inRoom = matchingRequest.roomId != null, fromDevice = cryptoStore.getDeviceId(), requestId = msg.requestId @@ -564,10 +624,10 @@ internal class VerificationActor @AssistedInject constructor( ) // should check if already one (and cancel it) - val tx = SasV1Transaction( + val tx = KotlinSasTransaction( channel = channel, transactionId = msg.requestId, - state = VerificationTxState.SasStarted, + state = SasTransactionState.SasStarted, otherUserId = msg.otherUserId, myUserId = myUserId, myTrustedMSK = cryptoStore.getMyCrossSigningInfo() @@ -589,16 +649,22 @@ internal class VerificationActor @AssistedInject constructor( msg.deferred.complete(tx) } - private suspend fun handleReciprocateQR(msg: VerificationIntent.ActionReciprocateQrVerification) { + private suspend fun handleActionReciprocateQR(msg: VerificationIntent.ActionReciprocateQrVerification) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] handle reciprocate for ${msg.requestId}") val matchingRequest = pendingRequests .flatMap { entry -> entry.value.filter { it.requestId == msg.requestId } }.firstOrNull() ?: return Unit.also { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] No matching request, abort ${msg.requestId}") msg.deferred.completeExceptionally(java.lang.IllegalArgumentException("Unknown request")) } if (matchingRequest.state != EVerificationState.Ready) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] Can't start if not ready, abort ${msg.requestId}") msg.deferred.completeExceptionally(java.lang.IllegalStateException("Can't start a non ready request")) return } @@ -607,21 +673,24 @@ internal class VerificationActor @AssistedInject constructor( msg.deferred.completeExceptionally(java.lang.IllegalArgumentException("Failed to find other device Id")) } - val existingTransaction = getExistingTransaction(msg.otherUserId, msg.requestId) + val existingTransaction = getExistingTransaction(msg.otherUserId, msg.requestId) // what if there is an existing?? if (existingTransaction != null) { // cancel or replace?? + Timber.tag(loggerTag.value) + .w("[${myUserId.take(8)}] There is already a started transaction for request ${msg.requestId}") return } val myMasterKey = crossSigningService.get() .getUserCrossSigningKeys(myUserId)?.masterKey()?.unpaddedBase64PublicKey - var canTrustOtherUserMasterKey = false // Check the other device view of my MSK val otherQrCodeData = msg.scannedData.toQrCodeData() when (otherQrCodeData) { null -> { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] Malformed QR code ${msg.requestId}") msg.deferred.completeExceptionally(IllegalArgumentException("Malformed QrCode data")) return } @@ -629,95 +698,87 @@ internal class VerificationActor @AssistedInject constructor( // key2 (aka otherUserMasterCrossSigningPublicKey) is what the one displaying the QR code (other user) think my MSK is. // Let's check that it's correct // If not -> Cancel - if (otherQrCodeData.otherUserMasterCrossSigningPublicKey != myMasterKey) { - Timber.d("## Verification QR: Invalid other master key ${otherQrCodeData.otherUserMasterCrossSigningPublicKey}") + val whatOtherThinksMyMskIs = otherQrCodeData.otherUserMasterCrossSigningPublicKey + if (whatOtherThinksMyMskIs != myMasterKey) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] ## Verification QR: Invalid other master key ${otherQrCodeData.otherUserMasterCrossSigningPublicKey}") cancelRequest(matchingRequest, CancelCode.MismatchedKeys) msg.deferred.complete(null) return - } else Unit + } + + val whatIThinkOtherMskIs = crossSigningService.get().getUserCrossSigningKeys(matchingRequest.otherUserId) + ?.masterKey() + ?.unpaddedBase64PublicKey + if (whatIThinkOtherMskIs != otherQrCodeData.userMasterCrossSigningPublicKey) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] ## Verification QR: Invalid other master key ${otherQrCodeData.otherUserMasterCrossSigningPublicKey}") + cancelRequest(matchingRequest, CancelCode.MismatchedKeys) + msg.deferred.complete(null) + return + } } is QrCodeData.SelfVerifyingMasterKeyTrusted -> { + if (matchingRequest.otherUserId != myUserId) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] Self mode qr with wrong user ${matchingRequest.otherUserId}") + cancelRequest(matchingRequest, CancelCode.MismatchedUser) + msg.deferred.complete(null) + return + } // key1 (aka userMasterCrossSigningPublicKey) is the session displaying the QR code view of our MSK. // Let's check that I see the same MSK // If not -> Cancel - if (otherQrCodeData.userMasterCrossSigningPublicKey != myMasterKey) { - Timber.d("## Verification QR: Invalid other master key ${otherQrCodeData.userMasterCrossSigningPublicKey}") + val whatOtherThinksOurMskIs = otherQrCodeData.userMasterCrossSigningPublicKey + if (whatOtherThinksOurMskIs != myMasterKey) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] ## Verification QR: Invalid other master key ${otherQrCodeData.userMasterCrossSigningPublicKey}") + cancelRequest(matchingRequest, CancelCode.MismatchedKeys) + msg.deferred.complete(null) + return + } + val whatOtherThinkMyDeviceKeyIs = otherQrCodeData.otherDeviceKey + val myDeviceKey = cryptoStore.getUserDevice(myUserId, cryptoStore.getDeviceId())?.fingerprint() + if (whatOtherThinkMyDeviceKeyIs != myDeviceKey) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] ## Verification QR: Invalid other device key ${otherQrCodeData.userMasterCrossSigningPublicKey}") cancelRequest(matchingRequest, CancelCode.MismatchedKeys) msg.deferred.complete(null) return - } else { - // I can trust the MSK then (i see the same one, and other session tell me it's trusted by him) - canTrustOtherUserMasterKey = true } } is QrCodeData.SelfVerifyingMasterKeyNotTrusted -> { + if (matchingRequest.otherUserId != myUserId) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] Self mode qr with wrong user ${matchingRequest.otherUserId}") + cancelRequest(matchingRequest, CancelCode.MismatchedUser) + msg.deferred.complete(null) + return + } // key2 (aka userMasterCrossSigningPublicKey) is the session displaying the QR code view of our MSK. // Let's check that it's the good one // If not -> Cancel - if (otherQrCodeData.userMasterCrossSigningPublicKey != myMasterKey) { - Timber.d("## Verification QR: Invalid other master key ${otherQrCodeData.userMasterCrossSigningPublicKey}") + val otherDeclaredDeviceKey = otherQrCodeData.deviceKey + val whatIThinkItIs = cryptoStore.getUserDevice(myUserId, otherDeviceId)?.fingerprint() + + if (otherDeclaredDeviceKey != whatIThinkItIs) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] ## Verification QR: Invalid other device key $otherDeviceId") + cancelRequest(matchingRequest, CancelCode.MismatchedKeys) + msg.deferred.complete(null) + } + + val ownMasterKeyTrustedAsSeenByOther = otherQrCodeData.userMasterCrossSigningPublicKey + if (ownMasterKeyTrustedAsSeenByOther != myMasterKey) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] ## Verification QR: Invalid other master key ${otherQrCodeData.userMasterCrossSigningPublicKey}") cancelRequest(matchingRequest, CancelCode.MismatchedKeys) msg.deferred.complete(null) return - } else { - // Nothing special here, we will send a reciprocate start event, and then the other session will trust it's view of the MSK } } } - val toVerifyDeviceIds = mutableListOf() - - // Let's now check the other user/device key material - when (otherQrCodeData) { - is QrCodeData.VerifyingAnotherUser -> { - // key1(aka userMasterCrossSigningPublicKey) is the MSK of the one displaying the QR code (i.e other user) - // Let's check that it matches what I think it should be - if (otherQrCodeData.userMasterCrossSigningPublicKey - != crossSigningService.get().getUserCrossSigningKeys(msg.otherUserId)?.masterKey()?.unpaddedBase64PublicKey) { - Timber.d("## Verification QR: Invalid user master key ${otherQrCodeData.userMasterCrossSigningPublicKey}") - cancelRequest(matchingRequest, CancelCode.MismatchedKeys) - msg.deferred.complete(null) - return - } else { - // It does so i should mark it as trusted - canTrustOtherUserMasterKey = true - } - } - is QrCodeData.SelfVerifyingMasterKeyTrusted -> { - // key2 (aka otherDeviceKey) is my current device key in POV of the one displaying the QR code (i.e other device) - // Let's check that it's correct - if (otherQrCodeData.otherDeviceKey - != cryptoStore.getUserDevice(myUserId, cryptoStore.getDeviceId())?.fingerprint()) { - Timber.d("## Verification QR: Invalid other device key ${otherQrCodeData.otherDeviceKey}") - cancelRequest(matchingRequest, CancelCode.MismatchedKeys) - msg.deferred.complete(null) - return - } else Unit // Nothing special here, we will send a reciprocate start event, and then the other session will trust my device - // and thus allow me to request SSSS secret - } - is QrCodeData.SelfVerifyingMasterKeyNotTrusted -> { - // key1 (aka otherDeviceKey) is the device key of the one displaying the QR code (i.e other device) - // Let's check that it matches what I have locally - if (otherQrCodeData.deviceKey - != cryptoStore.getUserDevice(msg.otherUserId, otherDeviceId ?: "")?.fingerprint()) { - Timber.d("## Verification QR: Invalid device key ${otherQrCodeData.deviceKey}") - cancelRequest(matchingRequest, CancelCode.MismatchedKeys) - msg.deferred.complete(null) - return - } else { - // Yes it does -> i should trust it and sign then upload the signature - toVerifyDeviceIds.add(otherDeviceId ?: "") - Unit - } - } - } - - if (!canTrustOtherUserMasterKey && toVerifyDeviceIds.isEmpty()) { - // Nothing to verify - cancelRequest(matchingRequest, CancelCode.MismatchedKeys) - return - } - // All checks are correct // Send the shared secret so that sender can trust me // qrCodeData.sharedSecret will be used to send the start request @@ -746,6 +807,8 @@ internal class VerificationActor @AssistedInject constructor( try { sendToOther(matchingRequest, EventType.KEY_VERIFICATION_START, message) } catch (failure: Throwable) { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}] Failed to send reciprocate message") msg.deferred.completeExceptionally(failure) return } @@ -754,21 +817,45 @@ internal class VerificationActor @AssistedInject constructor( eventFlow.emit(VerificationEvent.RequestUpdated(matchingRequest.toPendingVerificationRequest())) val tx = KotlinQRVerification( - qrCodeText = msg.scannedData, - state = VerificationTxState.WaitingOtherReciprocateConfirm, + channel = this.channel, + state = QRCodeVerificationState.Reciprocated, + qrCodeData = msg.scannedData.toQrCodeData(), method = VerificationMethod.QR_CODE_SCAN, transactionId = msg.requestId, otherUserId = msg.otherUserId, otherDeviceId = matchingRequest.otherDeviceId(), - isIncoming = false + isIncoming = false, + isToDevice = matchingRequest.roomId == null ) + addTransaction(tx) + msg.deferred.complete(tx) + } + + private suspend fun handleActionQRScanConfirmed(matchingRequest: KotlinVerificationRequest) { + val transaction = getExistingTransaction(matchingRequest.otherUserId, matchingRequest.requestId) + if (transaction == null) { + // return + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}]: No matching transaction for key tId:${matchingRequest.requestId}") + return + } + + if (transaction.state() == QRCodeVerificationState.WaitingForScanConfirmation) { + completeValidQRTransaction(transaction, matchingRequest) + } else { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}]: Unexpected confirm in state tId:${matchingRequest.requestId}") + // TODO throw? + cancelRequest(matchingRequest, CancelCode.MismatchedKeys) + return + } } private suspend fun handleReceiveKey(matchingRequest: KotlinVerificationRequest, msg: VerificationIntent.OnKeyReceived) { val requestId = msg.validKey.transactionId - val existing = getExistingTransaction(msg.fromUser, requestId) + val existing: KotlinSasTransaction = getExistingTransaction(msg.fromUser, requestId) ?: return Unit.also { Timber.tag(loggerTag.value) .v("[${myUserId.take(8)}]: No matching transaction for key tId:$requestId") @@ -776,9 +863,9 @@ internal class VerificationActor @AssistedInject constructor( // Existing should be in SAS key sent val isCorrectState = if (existing.isIncoming) { - existing.state == VerificationTxState.SasAccepted + existing.state == SasTransactionState.SasAccepted } else { - existing.state == VerificationTxState.SasKeySent + existing.state == SasTransactionState.SasKeySent } if (!isCorrectState) { @@ -792,7 +879,7 @@ internal class VerificationActor @AssistedInject constructor( if (existing.isIncoming) { // ok i can now send my key and compute the sas code val pubKey = existing.getSAS().publicKey - val keyMessage = SasV1Transaction.sasKeyMessage(matchingRequest.roomId != null, requestId, pubKey) + val keyMessage = KotlinSasTransaction.sasKeyMessage(matchingRequest.roomId != null, requestId, pubKey) try { sendToOther( matchingRequest, @@ -804,7 +891,7 @@ internal class VerificationActor @AssistedInject constructor( .v("[${myUserId.take(8)}]:i calculate SAS my key $pubKey their Key: $otherKey") } existing.calculateSASBytes(otherKey) - existing.state = VerificationTxState.SasShortCodeReady + existing.state = SasTransactionState.SasShortCodeReady if (BuildConfig.LOG_PRIVATE_DATA) { Timber.tag(loggerTag.value) .v("[${myUserId.take(8)}]:i CODE ${existing.getDecimalCodeRepresentation()}") @@ -813,7 +900,7 @@ internal class VerificationActor @AssistedInject constructor( } eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) } catch (failure: Throwable) { - existing.state = VerificationTxState.Cancelled(CancelCode.UserError, true) + existing.state = SasTransactionState.Cancelled(CancelCode.UserError, true) matchingRequest.state = EVerificationState.Cancelled matchingRequest.cancelCode = CancelCode.UserError eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) @@ -843,7 +930,7 @@ internal class VerificationActor @AssistedInject constructor( .v("[${myUserId.take(8)}]:o calculate SAS my key ${existing.getSAS().publicKey} their Key: $otherKey") } existing.calculateSASBytes(otherKey) - existing.state = VerificationTxState.SasShortCodeReady + existing.state = SasTransactionState.SasShortCodeReady eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) if (BuildConfig.LOG_PRIVATE_DATA) { Timber.tag(loggerTag.value) @@ -864,21 +951,21 @@ internal class VerificationActor @AssistedInject constructor( private suspend fun handleMacReceived(matchingRequest: KotlinVerificationRequest, msg: VerificationIntent.OnMacReceived) { val requestId = msg.validMac.transactionId - val existing = getExistingTransaction(msg.fromUser, requestId) + val existing: KotlinSasTransaction = getExistingTransaction(msg.fromUser, requestId) ?: return Unit.also { Timber.tag(loggerTag.value) .v("[${myUserId.take(8)}] on Mac for unknown transaction with id:$requestId") } when (existing.state) { - is VerificationTxState.SasMacSent -> { + is SasTransactionState.SasMacSent -> { existing.theirMac = msg.validMac finalizeSasTransaction(existing, msg.validMac, matchingRequest, existing.transactionId) } - is VerificationTxState.SasShortCodeReady -> { + is SasTransactionState.SasShortCodeReady -> { // I can start verify, store it existing.theirMac = msg.validMac - existing.state = VerificationTxState.SasMacReceived(false) + existing.state = SasTransactionState.SasMacReceived(false) eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) } else -> { @@ -901,14 +988,14 @@ internal class VerificationActor @AssistedInject constructor( msg.deferred.completeExceptionally(IllegalStateException("Request was cancelled")) } } - val existing = getExistingTransaction(transactionId) + val existing: KotlinSasTransaction = getExistingTransaction(transactionId) ?: return Unit.also { msg.deferred.completeExceptionally(IllegalStateException("Unknown Transaction")) } val isCorrectState = when (val state = existing.state) { - is VerificationTxState.SasShortCodeReady -> true - is VerificationTxState.SasMacReceived -> !state.codeConfirmed + is SasTransactionState.SasShortCodeReady -> true + is SasTransactionState.SasMacReceived -> !state.codeConfirmed else -> false } if (!isCorrectState) { @@ -927,25 +1014,122 @@ internal class VerificationActor @AssistedInject constructor( private suspend fun handleDoneReceived(matchingRequest: KotlinVerificationRequest, msg: VerificationIntent.OnDoneReceived) { val requestId = msg.transactionId - val existing = getExistingTransaction(msg.fromUser, requestId) + val existing: VerificationTransaction = getExistingTransaction(msg.fromUser, requestId) ?: return Unit.also { Timber.v("on accept received in room ${msg.viaRoom} for verification id:${requestId} in room ${matchingRequest.roomId}") } - val state = existing.state - val isCorrectState = state is VerificationTxState.Done && !state.otherDone + when { + existing is KotlinSasTransaction -> { + val state = existing.state + val isCorrectState = state is SasTransactionState.Done && !state.otherDone - if (isCorrectState) { - // XXX whatabout waiting for done? - matchingRequest.state = EVerificationState.Done - eventFlow.emit(VerificationEvent.RequestUpdated(matchingRequest.toPendingVerificationRequest())) -// updatePendingRequest( -// matchingRequest.copy( -// isSuccessful = true -// ) -// ) - } else { - // TODO cancel? + if (isCorrectState) { + existing.state = SasTransactionState.Done(true) + eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) + // we can forget about it + txMap[matchingRequest.otherUserId()]?.remove(matchingRequest.requestId) + // XXX whatabout waiting for done? + matchingRequest.state = EVerificationState.Done + eventFlow.emit(VerificationEvent.RequestUpdated(matchingRequest.toPendingVerificationRequest())) + } else { + // TODO cancel? + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}]: Unexpected done in state $state") + + cancelRequest(matchingRequest, CancelCode.UnexpectedMessage) + } + } + existing is KotlinQRVerification -> { + val state = existing.state() + when (state) { + QRCodeVerificationState.Reciprocated -> { + completeValidQRTransaction(existing, matchingRequest) + } + QRCodeVerificationState.WaitingForOtherDone -> { + matchingRequest.state = EVerificationState.Done + eventFlow.emit(VerificationEvent.RequestUpdated(matchingRequest.toPendingVerificationRequest())) + } + else -> { + Timber.tag(loggerTag.value) + .d("[${myUserId.take(8)}]: Unexpected done in state $state") + cancelRequest(matchingRequest, CancelCode.UnexpectedMessage) + } + } + } + else -> { + // unexpected message? + cancelRequest(matchingRequest, CancelCode.UnexpectedMessage) + } + } + } + + private suspend fun completeValidQRTransaction(existing: KotlinQRVerification, matchingRequest: KotlinVerificationRequest) { + var shouldRequestSecret = false + // Ok so the other side is fine let's trust what we need to trust + when (existing.qrCodeData) { + is QrCodeData.VerifyingAnotherUser -> { + // let's trust him + // it's his code scanned so user is him and other me + try { + crossSigningService.get().trustUser(matchingRequest.otherUserId) + } catch (failure: Throwable) { + // fail silently? + // at least it will be marked as trusted locally? + } + } + is QrCodeData.SelfVerifyingMasterKeyNotTrusted -> { + // the other device is the one that doesn't trust yet our MSK + // As all is good I can upload a signature for my new device + + // Also notify the secret share manager for the soon to come secret share requests + secretShareManager.onVerificationCompleteForDevice(matchingRequest.otherDeviceId()!!) + try { + crossSigningService.get().trustDevice(matchingRequest.otherDeviceId()!!) + } catch (failure: Throwable) { + // network problem?? + Timber.w("## Verification: Failed to sign new device ${matchingRequest.otherDeviceId()}, ${failure.localizedMessage}") + } + } + is QrCodeData.SelfVerifyingMasterKeyTrusted -> { + // I can trust my MSK + crossSigningService.get().markMyMasterKeyAsTrusted() + shouldRequestSecret = true + } + null -> { + // This shouldn't happen? cancel? + } + } + + sendToOther( + matchingRequest, + EventType.KEY_VERIFICATION_DONE, + if (matchingRequest.roomId != null) { + MessageVerificationDoneContent( + relatesTo = RelationDefaultContent( + RelationType.REFERENCE, + matchingRequest.requestId + ) + ) + } else { + KeyVerificationDone(matchingRequest.requestId) + } + ) + + existing.state = QRCodeVerificationState.Done + eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) + // we can forget about it + txMap[matchingRequest.otherUserId()]?.remove(matchingRequest.requestId) + matchingRequest.state = EVerificationState.WaitingForDone + eventFlow.emit(VerificationEvent.RequestUpdated(matchingRequest.toPendingVerificationRequest())) + + if (shouldRequestSecret) { + matchingRequest.otherDeviceId()?.let { otherDeviceId -> + secretShareManager.requestSecretTo(otherDeviceId, MASTER_KEY_SSSS_NAME) + secretShareManager.requestSecretTo(otherDeviceId, SELF_SIGNING_KEY_SSSS_NAME) + secretShareManager.requestSecretTo(otherDeviceId, USER_SIGNING_KEY_SSSS_NAME) + secretShareManager.requestSecretTo(otherDeviceId, KEYBACKUP_SECRET_SSSS_NAME) + } } } @@ -956,21 +1140,21 @@ internal class VerificationActor @AssistedInject constructor( msg.deferred.completeExceptionally(IllegalStateException("Unknown Request")) } - if (matchingRequest.state != EVerificationState.WeStarted - && matchingRequest.state != EVerificationState.Started) { + if (matchingRequest.state != EVerificationState.WeStarted && + matchingRequest.state != EVerificationState.Started) { return Unit.also { msg.deferred.completeExceptionally(IllegalStateException("Can't accept code in state: ${matchingRequest.state}")) } } - val existing = getExistingTransaction(transactionId) + val existing: KotlinSasTransaction = getExistingTransaction(transactionId) ?: return Unit.also { msg.deferred.completeExceptionally(IllegalStateException("Unknown Transaction")) } val isCorrectState = when (val state = existing.state) { - is VerificationTxState.SasShortCodeReady -> true - is VerificationTxState.SasMacReceived -> !state.codeConfirmed + is SasTransactionState.SasShortCodeReady -> true + is SasTransactionState.SasMacReceived -> !state.codeConfirmed else -> false } if (!isCorrectState) { @@ -981,7 +1165,7 @@ internal class VerificationActor @AssistedInject constructor( val macInfo = existing.computeMyMac() - val macMsg = SasV1Transaction.sasMacMessage(matchingRequest.roomId != null, transactionId, macInfo) + val macMsg = KotlinSasTransaction.sasMacMessage(matchingRequest.roomId != null, transactionId, macInfo) try { sendToOther(matchingRequest, EventType.KEY_VERIFICATION_MAC, macMsg) } catch (failure: Throwable) { @@ -995,7 +1179,7 @@ internal class VerificationActor @AssistedInject constructor( if (theirMac != null) { finalizeSasTransaction(existing, theirMac, matchingRequest, transactionId) } else { - existing.state = VerificationTxState.SasMacSent + existing.state = SasTransactionState.SasMacSent eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) } @@ -1003,7 +1187,7 @@ internal class VerificationActor @AssistedInject constructor( } private suspend fun finalizeSasTransaction( - existing: SasV1Transaction, + existing: KotlinSasTransaction, theirMac: ValidVerificationInfoMac, matchingRequest: KotlinVerificationRequest, transactionId: String @@ -1017,7 +1201,7 @@ internal class VerificationActor @AssistedInject constructor( Timber.tag(loggerTag.value) .v("[${myUserId.take(8)}] verify macs result $result id:$transactionId") when (result) { - is SasV1Transaction.MacVerificationResult.Success -> { + is KotlinSasTransaction.MacVerificationResult.Success -> { // mark the devices as locally trusted result.verifiedDeviceId.forEach { deviceId -> val actualTrustLevel = cryptoStore.getUserDevice(matchingRequest.otherUserId, deviceId)?.trustLevel @@ -1068,17 +1252,17 @@ internal class VerificationActor @AssistedInject constructor( } ) - existing.state = VerificationTxState.Done(false) + existing.state = SasTransactionState.Done(false) eventFlow.emit(VerificationEvent.TransactionUpdated(existing)) pastTransactions.getOrPut(transactionId) { mutableMapOf() }[transactionId] = existing txMap[matchingRequest.otherUserId]?.remove(transactionId) matchingRequest.state = EVerificationState.WaitingForDone eventFlow.emit(VerificationEvent.RequestUpdated(matchingRequest.toPendingVerificationRequest())) } - SasV1Transaction.MacVerificationResult.MismatchKeys, - SasV1Transaction.MacVerificationResult.MismatchMacCrossSigning, - is SasV1Transaction.MacVerificationResult.MismatchMacDevice, - SasV1Transaction.MacVerificationResult.NoDevicesVerified -> { + KotlinSasTransaction.MacVerificationResult.MismatchKeys, + KotlinSasTransaction.MacVerificationResult.MismatchMacCrossSigning, + is KotlinSasTransaction.MacVerificationResult.MismatchMacDevice, + KotlinSasTransaction.MacVerificationResult.NoDevicesVerified -> { cancelRequest(matchingRequest, CancelCode.MismatchedKeys) } } @@ -1126,7 +1310,7 @@ internal class VerificationActor @AssistedInject constructor( commonMethods ) - val message = SasV1Transaction.sasReady( + val message = KotlinSasTransaction.sasReady( inRoom = existing.roomId != null, requestId = msg.transactionId, methods = commonMethods, @@ -1533,11 +1717,17 @@ internal class VerificationActor @AssistedInject constructor( eventFlow.emit(VerificationEvent.RequestUpdated(request.toPendingVerificationRequest())) // should also update SAS/QR transaction - getExistingTransaction(request.otherUserId, request.requestId)?.let { - it.state = VerificationTxState.Cancelled(code, true) + getExistingTransaction(request.otherUserId, request.requestId)?.let { + it.state = SasTransactionState.Cancelled(code, true) txMap[request.otherUserId]?.remove(request.requestId) eventFlow.emit(VerificationEvent.TransactionUpdated(it)) } + getExistingTransaction(request.otherUserId, request.requestId)?.let { + it.state = QRCodeVerificationState.Cancelled + txMap[request.otherUserId]?.remove(request.requestId) + eventFlow.emit(VerificationEvent.TransactionUpdated(it)) + } + cancelRequest(request.requestId, request.roomId, request.otherUserId, request.otherDeviceId(), code) } @@ -1592,17 +1782,17 @@ internal class VerificationActor @AssistedInject constructor( throw java.lang.IllegalArgumentException("Unsupported hash method $hashMethod") } - private suspend fun addTransaction(tx: SasV1Transaction) { + private suspend fun addTransaction(tx: VerificationTransaction) { val txInnerMap = txMap.getOrPut(tx.otherUserId) { mutableMapOf() } txInnerMap[tx.transactionId] = tx eventFlow.emit(VerificationEvent.TransactionAdded(tx)) } - private fun getExistingTransaction(otherUserId: String, transactionId: String): SasV1Transaction? { - return txMap[otherUserId]?.get(transactionId) + private inline fun getExistingTransaction(otherUserId: String, transactionId: String): T? { + return txMap[otherUserId]?.get(transactionId) as? T } - private inline fun getExistingTransaction(transactionId: String, type: T): T? { + private inline fun getExistingTransaction(transactionId: String): T? { txMap.forEach { val match = it.value.values .firstOrNull { it.transactionId == transactionId } diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationIntent.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationIntent.kt index b6446752c0..6fb0a09b48 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationIntent.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationIntent.kt @@ -17,7 +17,6 @@ package org.matrix.android.sdk.internal.crypto.verification import kotlinx.coroutines.CompletableDeferred -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.ValidVerificationInfoReady import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoRequest @@ -106,6 +105,12 @@ internal sealed class VerificationIntent { val deferred: CompletableDeferred, ) : VerificationIntent() + data class ActionConfirmCodeWasScanned( + val otherUserId: String, + val requestId: String, + val deferred: CompletableDeferred, + ) : VerificationIntent() + data class OnStartReceived( val viaRoom: String?, val fromUser: String, diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt index 5f0793bb2b..db9ecf31ff 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/verification/VerificationMessageProcessor.kt @@ -23,8 +23,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationReadyContent -import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent -import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationStartContent import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.util.time.Clock @@ -56,7 +54,7 @@ internal class VerificationMessageProcessor @Inject constructor( return allowedTypes.contains(eventType) } - suspend fun process(roomId:String, event: Event) { + suspend fun process(roomId: String, event: Event) { Timber.v("## SAS Verification live observer: received msgId: ${event.eventId} msgtype: ${event.getClearType()} from ${event.senderId}") // If the request is in the future by more than 5 minutes or more than 10 minutes in the past, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/IVerificationRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/IVerificationRequest.kt index ce9eb13143..3c68909952 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/IVerificationRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/IVerificationRequest.kt @@ -16,13 +16,13 @@ package org.matrix.android.sdk.api.session.crypto.verification -import org.matrix.android.sdk.internal.crypto.verification.KotlinVerificationRequest - enum class EVerificationState { // outgoing started request WaitingForReady, + // for incoming Requested, + // both incoming/outgoing Ready, Started, @@ -34,15 +34,16 @@ enum class EVerificationState { } // TODO remove that -interface IVerificationRequest{ +interface IVerificationRequest { fun requestId(): String fun incoming(): Boolean fun otherUserId(): String fun roomId(): String? + // target devices in case of to_device self verification - fun targetDevices() : List? + fun targetDevices(): List? fun state(): EVerificationState fun ageLocalTs(): Long @@ -53,10 +54,9 @@ interface IVerificationRequest{ fun otherDeviceId(): String? - fun qrCodeText() : String? + fun qrCodeText(): String? - fun isFinished() : Boolean = state() == EVerificationState.Cancelled || state() == EVerificationState.Done + fun isFinished(): Boolean = state() == EVerificationState.Cancelled || state() == EVerificationState.Done fun cancelCode(): CancelCode? - } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/PendingVerificationRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/PendingVerificationRequest.kt index 1c705cc4df..632e90f5f5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/PendingVerificationRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/PendingVerificationRequest.kt @@ -15,13 +15,6 @@ */ package org.matrix.android.sdk.api.session.crypto.verification -import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN -import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SHOW -import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS -import java.util.UUID - - /** * Stores current pending verification requests. */ @@ -34,7 +27,7 @@ data class PendingVerificationRequest( val otherDeviceId: String?, // in case of verification via room, it will be not null val roomId: String?, - val transactionId: String,//? = null, + val transactionId: String, // ? = null, // val requestInfo: ValidVerificationInfoRequest? = null, // val readyInfo: ValidVerificationInfoReady? = null, val cancelConclusion: CancelCode? = null, @@ -52,5 +45,4 @@ data class PendingVerificationRequest( // val isReady: Boolean = readyInfo != null // // val isFinished: Boolean = isSuccessful || cancelConclusion != null - } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/QrCodeVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/QrCodeVerificationTransaction.kt index 66287862d8..2f7167d104 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/QrCodeVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/QrCodeVerificationTransaction.kt @@ -16,8 +16,22 @@ package org.matrix.android.sdk.api.session.crypto.verification +enum class QRCodeVerificationState { + // ie. we started + Reciprocated, + + // When started/scanned by other side and waiting for confirmation + // that was really scanned + WaitingForScanConfirmation, + WaitingForOtherDone, + Done, + Cancelled +} + interface QrCodeVerificationTransaction : VerificationTransaction { + fun state(): QRCodeVerificationState + /** * To use to display a qr code, for the other user to scan it. */ @@ -26,7 +40,7 @@ interface QrCodeVerificationTransaction : VerificationTransaction { /** * Call when you have scan the other user QR code. */ - suspend fun userHasScannedOtherQrCode(otherQrCodeText: String) +// suspend fun userHasScannedOtherQrCode(otherQrCodeText: String) /** * Call when you confirm that other user has scanned your QR code. @@ -37,4 +51,6 @@ interface QrCodeVerificationTransaction : VerificationTransaction { * Call when you do not confirm that other user has scanned your QR code. */ suspend fun otherUserDidNotScannedMyQrCode() + + override fun isSuccessful() = state() == QRCodeVerificationState.Done } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/SasVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/SasVerificationTransaction.kt index d5feec1a2d..0b48786a09 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/SasVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/SasVerificationTransaction.kt @@ -40,6 +40,10 @@ interface SasVerificationTransaction : VerificationTransaction { val KNOWN_SHORT_CODES = listOf(SasMode.EMOJI, SasMode.DECIMAL) } + fun state(): SasTransactionState + + override fun isSuccessful() = state() is SasTransactionState.Done + fun supportsEmoji(): Boolean fun getEmojiCodeRepresentation(): List diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationEvent.kt index fce40457f4..51df8c1548 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationEvent.kt @@ -23,8 +23,8 @@ sealed class VerificationEvent(val transactionId: String) { data class TransactionUpdated(val transaction: VerificationTransaction) : VerificationEvent(transaction.transactionId) } -fun VerificationEvent.getRequest() : PendingVerificationRequest? { - return when(this) { +fun VerificationEvent.getRequest(): PendingVerificationRequest? { + return when (this) { is VerificationEvent.RequestAdded -> this.request is VerificationEvent.RequestUpdated -> this.request is VerificationEvent.TransactionAdded -> null @@ -32,12 +32,11 @@ fun VerificationEvent.getRequest() : PendingVerificationRequest? { } } -fun VerificationEvent.getTransaction() : VerificationTransaction? { - return when(this) { +fun VerificationEvent.getTransaction(): VerificationTransaction? { + return when (this) { is VerificationEvent.RequestAdded -> null is VerificationEvent.RequestUpdated -> null is VerificationEvent.TransactionAdded -> this.transaction is VerificationEvent.TransactionUpdated -> this.transaction } } - diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTransaction.kt index d9a07353ac..ecd8f87898 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTransaction.kt @@ -18,8 +18,6 @@ package org.matrix.android.sdk.api.session.crypto.verification interface VerificationTransaction { - val state: VerificationTxState - val method: VerificationMethod val transactionId: String @@ -37,4 +35,6 @@ interface VerificationTransaction { suspend fun cancel(code: CancelCode) fun isToDeviceTransport(): Boolean + + fun isSuccessful(): Boolean } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt index e693bd736f..39ab125b5f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationTxState.kt @@ -16,6 +16,35 @@ package org.matrix.android.sdk.api.session.crypto.verification +sealed class SasTransactionState { + + object None : SasTransactionState() + + // I wend a start + object SasStarted : SasTransactionState() + + // I received a start and it was accepted + object SasAccepted : SasTransactionState() + + // I received an accept and sent my key + object SasKeySent : SasTransactionState() + + // Keys exchanged and code ready to be shared + object SasShortCodeReady : SasTransactionState() + + // I received the other Mac, but might have not yet confirmed the short code + // at that time (other side already confirmed) + data class SasMacReceived(val codeConfirmed: Boolean) : SasTransactionState() + + // I confirmed the code and sent my mac + object SasMacSent : SasTransactionState() + + // I am done, waiting for other Done + data class Done(val otherDone: Boolean) : SasTransactionState() + + data class Cancelled(val cancelCode: CancelCode, val byMe: Boolean) : SasTransactionState() +} + sealed class VerificationTxState { /** * Uninitialized state. @@ -42,24 +71,24 @@ sealed class VerificationTxState { // object MacSent : VerificationSasTxState() // object Verifying : VerificationSasTxState() - // I wend a start - object SasStarted : VerificationSasTxState() - - // I received a start and it was accepted - object SasAccepted : VerificationSasTxState() - - // I received an accept and sent my key - object SasKeySent : VerificationSasTxState() - - // Keys exchanged and code ready to be shared - object SasShortCodeReady : VerificationSasTxState() - - // I received the other Mac, but might have not yet confirmed the short code - // at that time (other side already confirmed) - data class SasMacReceived(val codeConfirmed: Boolean) : VerificationSasTxState() - - // I confirmed the code and sent my mac - object SasMacSent : VerificationSasTxState() +// // I wend a start +// object SasStarted : VerificationSasTxState() +// +// // I received a start and it was accepted +// object SasAccepted : VerificationSasTxState() +// +// // I received an accept and sent my key +// object SasKeySent : VerificationSasTxState() +// +// // Keys exchanged and code ready to be shared +// object SasShortCodeReady : VerificationSasTxState() +// +// // I received the other Mac, but might have not yet confirmed the short code +// // at that time (other side already confirmed) +// data class SasMacReceived(val codeConfirmed: Boolean) : VerificationSasTxState() +// +// // I confirmed the code and sent my mac +// object SasMacSent : VerificationSasTxState() // I am done, waiting for other Done data class Done(val otherDone: Boolean) : VerificationSasTxState() @@ -67,13 +96,13 @@ sealed class VerificationTxState { /** * Specific for QR code. */ - abstract class VerificationQrTxState : VerificationTxState() - - /** - * Will be used to ask the user if the other user has correctly scanned. - */ - object QrScannedByOther : VerificationQrTxState() - object WaitingOtherReciprocateConfirm : VerificationQrTxState() +// abstract class VerificationQrTxState : VerificationTxState() +// +// /** +// * Will be used to ask the user if the other user has correctly scanned. +// */ +// object QrScannedByOther : VerificationQrTxState() +// object WaitingOtherReciprocateConfirm : VerificationQrTxState() /** * Terminal states. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationListenersHolder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationListenersHolder.kt index 57c0fc25a1..66e3ebeae8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationListenersHolder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationListenersHolder.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.crypto.verification import android.os.Handler import android.os.Looper -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.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt index 37d8acfa69..16c423da5b 100644 --- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt @@ -31,9 +31,6 @@ import im.vector.app.features.createdirect.CreateDirectRoomViewModel import im.vector.app.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel import im.vector.app.features.crypto.quads.SharedSecureStorageViewModel import im.vector.app.features.crypto.recover.BootstrapSharedViewModel -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodViewModel -import im.vector.app.features.crypto.verification.emoji.VerificationEmojiCodeViewModel import im.vector.app.features.crypto.verification.user.UserVerificationViewModel import im.vector.app.features.devtools.RoomDevToolViewModel import im.vector.app.features.discovery.DiscoverySettingsViewModel @@ -512,15 +509,10 @@ interface MavericksViewModelModule { @MavericksViewModelKey(MessageActionsViewModel::class) fun messageActionsViewModelFactory(factory: MessageActionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *> - @Binds - @IntoMap - @MavericksViewModelKey(VerificationChooseMethodViewModel::class) - fun verificationChooseMethodViewModelFactory(factory: VerificationChooseMethodViewModel.Factory): MavericksAssistedViewModelFactory<*, *> - - @Binds - @IntoMap - @MavericksViewModelKey(VerificationEmojiCodeViewModel::class) - fun verificationEmojiCodeViewModelFactory(factory: VerificationEmojiCodeViewModel.Factory): MavericksAssistedViewModelFactory<*, *> +// @Binds +// @IntoMap +// @MavericksViewModelKey(VerificationChooseMethodViewModel::class) +// fun verificationChooseMethodViewModelFactory(factory: VerificationChooseMethodViewModel.Factory): MavericksAssistedViewModelFactory<*, *> @Binds @IntoMap @@ -592,11 +584,10 @@ interface MavericksViewModelModule { @MavericksViewModelKey(BootstrapSharedViewModel::class) fun bootstrapSharedViewModelFactory(factory: BootstrapSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *> - @Binds - @IntoMap - @MavericksViewModelKey(VerificationBottomSheetViewModel::class) - fun verificationBottomSheetViewModelFactory(factory: VerificationBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *> - +// @Binds +// @IntoMap +// @MavericksViewModelKey(VerificationBottomSheetViewModel::class) +// fun verificationBottomSheetViewModelFactory(factory: VerificationBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *> @Binds @IntoMap diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt b/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt index e3972e1521..81a09bef3d 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt @@ -25,7 +25,6 @@ import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.session.coroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.cancellable @@ -39,11 +38,11 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest import org.matrix.android.sdk.api.session.crypto.model.SecretShareRequest +import org.matrix.android.sdk.api.session.crypto.verification.SasTransactionState 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.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -275,8 +274,8 @@ class KeyRequestHandler @Inject constructor( override fun transactionUpdated(tx: VerificationTransaction) { if (tx is SasVerificationTransaction) { - val state = tx.state - if (state == VerificationTxState.Verified) { + val state = tx.state() + if (state is SasTransactionState.Done) { // ok it's verified, see if we have key request for that shareAllSessions("${tx.otherDeviceId}${tx.otherUserId}") popupAlertManager.cancelAlert("ikr_${tx.otherDeviceId}${tx.otherUserId}") diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt index 9332b10781..3a3797af22 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt @@ -37,10 +37,11 @@ import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest +import org.matrix.android.sdk.api.session.crypto.verification.SasTransactionState +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.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.getUserOrDefault import org.matrix.android.sdk.api.util.toMatrixItem import timber.log.Timber @@ -89,8 +90,9 @@ class IncomingVerificationRequestHandler @Inject constructor( // TODO maybe check also if val uid = "kvr_${tx.transactionId}" // TODO we don't have that anymore? as it has to be requested first? - when (tx.state) { - is VerificationTxState.SasStarted -> { + if (tx !is SasVerificationTransaction) return + when (tx.state()) { + is SasTransactionState.SasStarted -> { // Add a notification for every incoming request // val user = session.getUserOrDefault(tx.otherUserId).toMatrixItem() // val name = user.getBestName() @@ -139,7 +141,7 @@ class IncomingVerificationRequestHandler @Inject constructor( // } // popupAlertManager.postVectorAlert(alert) } - is VerificationTxState.TerminalTxState -> { + is SasTransactionState.Done -> { // cancel related notification popupAlertManager.cancelAlert(uid) } @@ -186,7 +188,7 @@ class IncomingVerificationRequestHandler @Inject constructor( val roomId = pr.roomId if (roomId.isNullOrBlank()) { // TODO - //it.navigator.waitSessionVerification(it) + // it.navigator.waitSessionVerification(it) } else { it.navigator.openRoom( context = it, @@ -213,9 +215,9 @@ class IncomingVerificationRequestHandler @Inject constructor( override fun verificationRequestUpdated(pr: PendingVerificationRequest) { // If an incoming request is readied (by another device?) we should discard the alert - if (pr.isIncoming && (pr.state == EVerificationState.HandledByOtherSession - || pr.state == EVerificationState.Started - || pr.state == EVerificationState.WeStarted)) { + if (pr.isIncoming && (pr.state == EVerificationState.HandledByOtherSession || + pr.state == EVerificationState.Started || + pr.state == EVerificationState.WeStarted)) { popupAlertManager.cancelAlert(uniqueIdForVerificationRequest(pr)) } } 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 index e4a2b294d1..8580a324a3 100644 --- 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 @@ -1,266 +1,228 @@ -/* - * 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 -> { +// /* +// * 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( @@ -284,156 +246,194 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment 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( +// // 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 = session.myUserId, -// selfVerificationMode = true +// 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 +// ) +// ) // } - -// 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 +// 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" // } -// return null // } +// +// // 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/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt index 9ebe197100..61e70265a4 100644 --- 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 @@ -1,665 +1,665 @@ -/* - * 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 { +// /* +// * 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 // -// var autoReady = false -// val pr = if (initialState.selfVerificationMode) { -// // See if active tx for this user and take it +// 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 // -// 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) -// } +// 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 { // -// val sasTx = (pr?.transactionId ?: initialState.transactionId)?.let { -// session.cryptoService().verificationService().getExistingTransaction(initialState.otherUserId, it) as? SasVerificationTransaction -// } +// constructor(args: VerificationBottomSheet.VerificationArgs) : this( +// otherUserId = args.otherUserId, +// verificationId = args.verificationId, +// selfVerificationMode = args.selfVerificationMode, +// roomId = args.roomId, +// otherUserMxItem = MatrixItem.UserItem(args.otherUserId), +// ) +// } // -// val qrTx = (pr?.transactionId ?: initialState.transactionId)?.let { -// session.cryptoService().verificationService().getExistingTransaction(initialState.otherUserId, it) as? QrCodeVerificationTransaction -// } +// 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( -// 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 ?: "" -// ) +// copy(isVerificationRequired = wellKnown?.isSecureBackupRequired().orFalse()) // } // } - } - - 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() +// +// +// // 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 ?: "" +// // ) +// // } +// // } // } - - 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>(ins, action.alias) - val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys( - res?.get(MASTER_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 - try { - session.cryptoService().crossSigningService().trustDevice(session.sessionParams.deviceId) - } catch (failure: Exception) { - Timber.w(failure, "Failed to sign my device after recovery") - } - - setState { - copy( - verifyingFrom4S = false, - verifiedFromPrivateKeys = true - ) - } - - // try the keybackup - tentativeRestoreBackup(res) - } else { - setState { - copy( - verifyingFrom4S = false - ) - } - // POP UP something - _viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys))) - } - } - } catch (failure: Throwable) { - setState { - copy( - verifyingFrom4S = false - ) - } - _viewEvents.post( - VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)) - ) - } - } - } - - private fun tentativeRestoreBackup(res: Map?) { - // on session scope because will happen after viewmodel is cleared - session.coroutineScope.launch { - // It's not a good idea to download the full backup, it might take very long - // and use a lot of resources - // Just check that the key is valid and store it, the backup will be used megolm session per - // megolm session when an UISI is encountered - try { - val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also { - Timber.v("## Keybackup secret not restored from SSSS") - } - - val version = session.cryptoService().keysBackupService().getCurrentVersion()?.toKeysVersionResult() ?: return@launch - - val recoveryKey = computeRecoveryKey(secret.fromBase64()) - val backupRecoveryKey = BackupUtils.recoveryKeyFromBase58(recoveryKey) - val isValid = backupRecoveryKey - ?.let { session.cryptoService().keysBackupService().isValidRecoveryKeyForCurrentVersion(it) } - ?: false - if (isValid) { - session.cryptoService().keysBackupService().saveBackupRecoveryKey(backupRecoveryKey, version.version) - } - session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true) - } catch (failure: Throwable) { - // Just ignore for now - Timber.e(failure, "## Failed to restore backup after SSSS recovery") - } - } - } - +// +// 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>(ins, action.alias) +// val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys( +// res?.get(MASTER_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 +// try { +// session.cryptoService().crossSigningService().trustDevice(session.sessionParams.deviceId) +// } catch (failure: Exception) { +// Timber.w(failure, "Failed to sign my device after recovery") +// } +// +// setState { +// copy( +// verifyingFrom4S = false, +// verifiedFromPrivateKeys = true +// ) +// } +// +// // try the keybackup +// tentativeRestoreBackup(res) +// } else { +// setState { +// copy( +// verifyingFrom4S = false +// ) +// } +// // POP UP something +// _viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys))) +// } +// } +// } catch (failure: Throwable) { +// setState { +// copy( +// verifyingFrom4S = false +// ) +// } +// _viewEvents.post( +// VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)) +// ) +// } +// } +// } +// +// private fun tentativeRestoreBackup(res: Map?) { +// // on session scope because will happen after viewmodel is cleared +// session.coroutineScope.launch { +// // It's not a good idea to download the full backup, it might take very long +// // and use a lot of resources +// // Just check that the key is valid and store it, the backup will be used megolm session per +// // megolm session when an UISI is encountered +// try { +// val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also { +// Timber.v("## Keybackup secret not restored from SSSS") +// } +// +// val version = session.cryptoService().keysBackupService().getCurrentVersion()?.toKeysVersionResult() ?: return@launch +// +// val recoveryKey = computeRecoveryKey(secret.fromBase64()) +// val backupRecoveryKey = BackupUtils.recoveryKeyFromBase58(recoveryKey) +// val isValid = backupRecoveryKey +// ?.let { session.cryptoService().keysBackupService().isValidRecoveryKeyForCurrentVersion(it) } +// ?: false +// if (isValid) { +// session.cryptoService().keysBackupService().saveBackupRecoveryKey(backupRecoveryKey, version.version) +// } +// session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true) +// } catch (failure: Throwable) { +// // Just ignore for now +// Timber.e(failure, "## Failed to restore backup after SSSS recovery") +// } +// } +// } +// +// // override fun transactionCreated(tx: VerificationTransaction) { +// // transactionUpdated(tx) +// // } +// // +// // override fun transactionUpdated(tx: VerificationTransaction) = withState { state -> +// // if (state.selfVerificationMode && state.transactionId == null) { +// // // is this an incoming with that user +// // if (tx.isIncoming && tx.otherUserId == state.otherUserId) { +// // // Also auto accept incoming if needed! +// // if (tx is IncomingSasVerificationTransaction) { +// // if (tx.uxState == IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT) { +// // tx.performAccept() +// // } +// // } +// // // Use this one! +// // setState { +// // copy( +// // transactionId = tx.transactionId, +// // sasTransactionState = tx.state.takeIf { tx is SasVerificationTransaction }, +// // qrTransactionState = tx.state.takeIf { tx is QrCodeVerificationTransaction } +// // ) +// // } +// // } +// // } +// // +// // when (tx) { +// // is SasVerificationTransaction -> { +// // if (tx.transactionId == (state.pendingRequest.invoke()?.transactionId ?: state.transactionId)) { +// // // A SAS tx has been started following this request +// // setState { +// // copy( +// // transactionId = tx.transactionId, +// // sasTransactionState = tx.state.takeIf { tx is SasVerificationTransaction }, +// // qrTransactionState = tx.state.takeIf { tx is QrCodeVerificationTransaction } +// // ) +// // } +// // } +// // } +// // +// // when (tx) { +// // is SasVerificationTransaction -> { +// // if (tx.transactionId == (state.pendingRequest.invoke()?.transactionId ?: state.transactionId)) { +// // // A SAS tx has been started following this request +// // setState { +// // copy( +// // sasTransactionState = tx.state +// // ) +// // } +// // } +// // } +// // is QrCodeVerificationTransaction -> { +// // if (tx.transactionId == (state.pendingRequest.invoke()?.transactionId ?: state.transactionId)) { +// // // A QR tx has been started following this request +// // setState { +// // copy( +// // qrTransactionState = tx.state +// // ) +// // } +// // } +// // } +// // } +// // } +// // } +// // override fun transactionCreated(tx: VerificationTransaction) { // transactionUpdated(tx) // } // // override fun transactionUpdated(tx: VerificationTransaction) = withState { state -> -// if (state.selfVerificationMode && state.transactionId == null) { -// // is this an incoming with that user -// if (tx.isIncoming && tx.otherUserId == state.otherUserId) { -// // Also auto accept incoming if needed! -// if (tx is IncomingSasVerificationTransaction) { -// if (tx.uxState == IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT) { -// tx.performAccept() -// } -// } -// // Use this one! -// setState { -// copy( -// transactionId = tx.transactionId, -// sasTransactionState = tx.state.takeIf { tx is SasVerificationTransaction }, -// qrTransactionState = tx.state.takeIf { tx is QrCodeVerificationTransaction } -// ) -// } -// } -// } +// Timber.v("transactionUpdated: $tx") +// if (tx.transactionId != state.transactionId) return@withState +// if (tx is SasVerificationTransaction) { +// // setState { +// // copy( +// // sasTransactionState = tx.state +// // ) +// // } +// } else if (tx is QrCodeVerificationTransaction) { // -// when (tx) { -// is SasVerificationTransaction -> { -// if (tx.transactionId == (state.pendingRequest.invoke()?.transactionId ?: state.transactionId)) { -// // A SAS tx has been started following this request -// setState { -// copy( -// transactionId = tx.transactionId, -// sasTransactionState = tx.state.takeIf { tx is SasVerificationTransaction }, -// qrTransactionState = tx.state.takeIf { tx is QrCodeVerificationTransaction } -// ) -// } -// } -// } -// -// when (tx) { -// is SasVerificationTransaction -> { -// if (tx.transactionId == (state.pendingRequest.invoke()?.transactionId ?: state.transactionId)) { -// // A SAS tx has been started following this request -// setState { -// copy( -// sasTransactionState = tx.state -// ) -// } -// } -// } -// is QrCodeVerificationTransaction -> { -// if (tx.transactionId == (state.pendingRequest.invoke()?.transactionId ?: state.transactionId)) { -// // A QR tx has been started following this request -// setState { -// copy( -// qrTransactionState = tx.state -// ) -// } -// } -// } -// } // } +// // handleTransactionUpdate(state, tx) // } - - override fun transactionCreated(tx: VerificationTransaction) { - transactionUpdated(tx) - } - - override fun transactionUpdated(tx: VerificationTransaction) = withState { state -> - Timber.v("transactionUpdated: $tx") - if (tx.transactionId != state.transactionId) return@withState - if (tx is SasVerificationTransaction) { -// setState { -// copy( -// sasTransactionState = tx.state -// ) -// } - } else if (tx is QrCodeVerificationTransaction) { - - } - // handleTransactionUpdate(state, tx) - } - - override fun verificationRequestCreated(pr: PendingVerificationRequest) { - verificationRequestUpdated(pr) - } - - override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state -> - Timber.v("VerificationRequestUpdated: $pr") - if (pr.transactionId != state.pendingRequest.invoke()?.transactionId) return@withState - setState { - copy(pendingRequest = Success(pr)) - } -// if (state.selfVerificationMode && state.pendingRequest.invoke() == null && state.transactionId == null) { -// // is this an incoming with that user -// if (pr.isIncoming && pr.otherUserId == state.otherUserId) { -// if (!pr.isReady) { -// // auto ready in this case, as we are waiting -// // TODO, can I be here in DM mode? in this case should test if roomID is null? -// viewModelScope.launch { -// session.cryptoService().verificationService() -// .readyPendingVerification( -// supportedVerificationMethodsProvider.provide(), -// pr.otherUserId, -// pr.transactionId -// ) -// } -// } // -// // Use this one! -// setState { -// copy( -// transactionId = pr.transactionId, -// pendingRequest = Success(pr) -// ) -// } -// return@withState -// } -// } +// override fun verificationRequestCreated(pr: PendingVerificationRequest) { +// verificationRequestUpdated(pr) +// } // -// if (state.transactionId == pr.transactionId) { -// setState { -// copy( -// pendingRequest = Success(pr) -// ) -// } +// override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state -> +// Timber.v("VerificationRequestUpdated: $pr") +// if (pr.transactionId != state.pendingRequest.invoke()?.transactionId) return@withState +// setState { +// copy(pendingRequest = Success(pr)) // } - } -} +// // if (state.selfVerificationMode && state.pendingRequest.invoke() == null && state.transactionId == null) { +// // // is this an incoming with that user +// // if (pr.isIncoming && pr.otherUserId == state.otherUserId) { +// // if (!pr.isReady) { +// // // auto ready in this case, as we are waiting +// // // TODO, can I be here in DM mode? in this case should test if roomID is null? +// // viewModelScope.launch { +// // session.cryptoService().verificationService() +// // .readyPendingVerification( +// // supportedVerificationMethodsProvider.provide(), +// // pr.otherUserId, +// // pr.transactionId +// // ) +// // } +// // } +// // +// // // Use this one! +// // setState { +// // copy( +// // transactionId = pr.transactionId, +// // pendingRequest = Success(pr) +// // ) +// // } +// // return@withState +// // } +// // } +// // +// // if (state.transactionId == pr.transactionId) { +// // setState { +// // copy( +// // pendingRequest = Success(pr) +// // ) +// // } +// // } +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt index 600d5e1be1..e31bfc701c 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt @@ -1,109 +1,109 @@ -/* - * 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.cancel - -import androidx.core.text.toSpannable -import com.airbnb.epoxy.EpoxyController -import im.vector.app.R -import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider -import im.vector.app.core.utils.colorizeMatchingText -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem -import im.vector.app.features.displayname.getBestName -import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence -import javax.inject.Inject - -class VerificationCancelController @Inject constructor( - private val stringProvider: StringProvider, - private val colorProvider: ColorProvider -) : EpoxyController() { - - var listener: Listener? = null - - private var viewState: VerificationBottomSheetViewState? = null - - fun update(viewState: VerificationBottomSheetViewState) { - this.viewState = viewState - requestModelBuild() - } - - override fun buildModels() { - val state = viewState ?: return - val host = this - if (state.isMe) { - if (state.currentDeviceCanCrossSign) { - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_trusted).toEpoxyCharSequence()) - } - } else { - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_untrusted).toEpoxyCharSequence()) - } - } - } else { - val otherUserID = state.otherUserId - val otherDisplayName = state.otherUserMxItem.getBestName() - bottomSheetVerificationNoticeItem { - id("notice") - notice( - EpoxyCharSequence( - host.stringProvider.getString(R.string.verify_cancel_other, otherDisplayName, otherUserID) - .toSpannable() - .colorizeMatchingText(otherUserID, host.colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)) - ) - ) - } - } - - bottomSheetDividerItem { - id("sep0") - } - - bottomSheetVerificationActionItem { - id("cancel") - title(host.stringProvider.getString(R.string.action_skip)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - listener { host.listener?.onTapCancel() } - } - - bottomSheetDividerItem { - id("sep1") - } - - bottomSheetVerificationActionItem { - id("continue") - title(host.stringProvider.getString(R.string._continue)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - listener { host.listener?.onTapContinue() } - } - } - - interface Listener { - fun onTapCancel() - fun onTapContinue() - } -} +// /* +// * 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.cancel +// +// import androidx.core.text.toSpannable +// import com.airbnb.epoxy.EpoxyController +// import im.vector.app.R +// import im.vector.app.core.epoxy.bottomSheetDividerItem +// import im.vector.app.core.resources.ColorProvider +// import im.vector.app.core.resources.StringProvider +// import im.vector.app.core.utils.colorizeMatchingText +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +// import im.vector.app.features.displayname.getBestName +// import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence +// import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +// import javax.inject.Inject +// +// class VerificationCancelController @Inject constructor( +// private val stringProvider: StringProvider, +// private val colorProvider: ColorProvider +// ) : EpoxyController() { +// +// var listener: Listener? = null +// +// private var viewState: VerificationBottomSheetViewState? = null +// +// fun update(viewState: VerificationBottomSheetViewState) { +// this.viewState = viewState +// requestModelBuild() +// } +// +// override fun buildModels() { +// val state = viewState ?: return +// val host = this +// if (state.isMe) { +// if (state.currentDeviceCanCrossSign) { +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_trusted).toEpoxyCharSequence()) +// } +// } else { +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_untrusted).toEpoxyCharSequence()) +// } +// } +// } else { +// val otherUserID = state.otherUserId +// val otherDisplayName = state.otherUserMxItem.getBestName() +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice( +// EpoxyCharSequence( +// host.stringProvider.getString(R.string.verify_cancel_other, otherDisplayName, otherUserID) +// .toSpannable() +// .colorizeMatchingText(otherUserID, host.colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)) +// ) +// ) +// } +// } +// +// bottomSheetDividerItem { +// id("sep0") +// } +// +// bottomSheetVerificationActionItem { +// id("cancel") +// title(host.stringProvider.getString(R.string.action_skip)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// listener { host.listener?.onTapCancel() } +// } +// +// bottomSheetDividerItem { +// id("sep1") +// } +// +// bottomSheetVerificationActionItem { +// id("continue") +// title(host.stringProvider.getString(R.string._continue)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// listener { host.listener?.onTapContinue() } +// } +// } +// +// interface Listener { +// fun onTapCancel() +// fun onTapContinue() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelFragment.kt index c972f7834d..aaf811625e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelFragment.kt @@ -1,73 +1,73 @@ -/* - * 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.cancel - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.airbnb.mvrx.parentFragmentViewModel -import com.airbnb.mvrx.withState -import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.core.extensions.cleanup -import im.vector.app.core.extensions.configureWith -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import javax.inject.Inject - -@AndroidEntryPoint -class VerificationCancelFragment : - VectorBaseFragment(), - VerificationCancelController.Listener { - - @Inject lateinit var controller: VerificationCancelController - - private val viewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { - return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - setupRecyclerView() - } - - override fun onDestroyView() { - views.bottomSheetVerificationRecyclerView.cleanup() - controller.listener = null - super.onDestroyView() - } - - private fun setupRecyclerView() { - views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) - controller.listener = this - } - - override fun invalidate() = withState(viewModel) { state -> - controller.update(state) - } - - override fun onTapCancel() { - viewModel.confirmCancel() - } - - override fun onTapContinue() { - viewModel.continueFromCancel() - } -} +// /* +// * 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.cancel +// +// import android.os.Bundle +// import android.view.LayoutInflater +// import android.view.View +// import android.view.ViewGroup +// import com.airbnb.mvrx.parentFragmentViewModel +// import com.airbnb.mvrx.withState +// import dagger.hilt.android.AndroidEntryPoint +// import im.vector.app.core.extensions.cleanup +// import im.vector.app.core.extensions.configureWith +// import im.vector.app.core.platform.VectorBaseFragment +// import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel +// import javax.inject.Inject +// +// @AndroidEntryPoint +// class VerificationCancelFragment : +// VectorBaseFragment(), +// VerificationCancelController.Listener { +// +// @Inject lateinit var controller: VerificationCancelController +// +// private val viewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) +// +// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { +// return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// setupRecyclerView() +// } +// +// override fun onDestroyView() { +// views.bottomSheetVerificationRecyclerView.cleanup() +// controller.listener = null +// super.onDestroyView() +// } +// +// private fun setupRecyclerView() { +// views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) +// controller.listener = this +// } +// +// override fun invalidate() = withState(viewModel) { state -> +// controller.update(state) +// } +// +// override fun onTapCancel() { +// viewModel.confirmCancel() +// } +// +// override fun onTapContinue() { +// viewModel.continueFromCancel() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt index a7c987f97e..cc4026d532 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt @@ -1,84 +1,84 @@ -/* - * 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.cancel - -import com.airbnb.epoxy.EpoxyController -import im.vector.app.R -import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem -import im.vector.app.features.html.EventHtmlRenderer -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence -import javax.inject.Inject - -class VerificationNotMeController @Inject constructor( - private val stringProvider: StringProvider, - private val colorProvider: ColorProvider, - private val eventHtmlRenderer: EventHtmlRenderer -) : EpoxyController() { - - var listener: Listener? = null - - private var viewState: VerificationBottomSheetViewState? = null - - fun update(viewState: VerificationBottomSheetViewState) { - this.viewState = viewState - requestModelBuild() - } - - override fun buildModels() { - val host = this - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verify_not_me_self_verification)).toEpoxyCharSequence()) - } - - bottomSheetDividerItem { - id("sep0") - } - - bottomSheetVerificationActionItem { - id("skip") - title(host.stringProvider.getString(R.string.action_skip)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.onTapSkip() } - } - - bottomSheetDividerItem { - id("sep1") - } - - bottomSheetVerificationActionItem { - id("settings") - title(host.stringProvider.getString(R.string.settings)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - listener { host.listener?.onTapSettings() } - } - } - - interface Listener { - fun onTapSkip() - fun onTapSettings() - } -} +// /* +// * 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.cancel +// +// import com.airbnb.epoxy.EpoxyController +// import im.vector.app.R +// import im.vector.app.core.epoxy.bottomSheetDividerItem +// import im.vector.app.core.resources.ColorProvider +// import im.vector.app.core.resources.StringProvider +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +// import im.vector.app.features.html.EventHtmlRenderer +// import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +// import javax.inject.Inject +// +// class VerificationNotMeController @Inject constructor( +// private val stringProvider: StringProvider, +// private val colorProvider: ColorProvider, +// private val eventHtmlRenderer: EventHtmlRenderer +// ) : EpoxyController() { +// +// var listener: Listener? = null +// +// private var viewState: VerificationBottomSheetViewState? = null +// +// fun update(viewState: VerificationBottomSheetViewState) { +// this.viewState = viewState +// requestModelBuild() +// } +// +// override fun buildModels() { +// val host = this +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verify_not_me_self_verification)).toEpoxyCharSequence()) +// } +// +// bottomSheetDividerItem { +// id("sep0") +// } +// +// bottomSheetVerificationActionItem { +// id("skip") +// title(host.stringProvider.getString(R.string.action_skip)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.onTapSkip() } +// } +// +// bottomSheetDividerItem { +// id("sep1") +// } +// +// bottomSheetVerificationActionItem { +// id("settings") +// title(host.stringProvider.getString(R.string.settings)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// listener { host.listener?.onTapSettings() } +// } +// } +// +// interface Listener { +// fun onTapSkip() +// fun onTapSettings() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeFragment.kt index 05632bdfc3..f01abcdfa7 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeFragment.kt @@ -1,73 +1,73 @@ -/* - * 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.cancel - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.airbnb.mvrx.parentFragmentViewModel -import com.airbnb.mvrx.withState -import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.core.extensions.cleanup -import im.vector.app.core.extensions.configureWith -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import javax.inject.Inject - -@AndroidEntryPoint -class VerificationNotMeFragment : - VectorBaseFragment(), - VerificationNotMeController.Listener { - - @Inject lateinit var controller: VerificationNotMeController - - private val viewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { - return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - setupRecyclerView() - } - - override fun onDestroyView() { - views.bottomSheetVerificationRecyclerView.cleanup() - controller.listener = null - super.onDestroyView() - } - - private fun setupRecyclerView() { - views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) - controller.listener = this - } - - override fun invalidate() = withState(viewModel) { state -> - controller.update(state) - } - - override fun onTapSkip() { - viewModel.continueFromWasNotMe() - } - - override fun onTapSettings() { - viewModel.goToSettings() - } -} +// /* +// * 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.cancel +// +// import android.os.Bundle +// import android.view.LayoutInflater +// import android.view.View +// import android.view.ViewGroup +// import com.airbnb.mvrx.parentFragmentViewModel +// import com.airbnb.mvrx.withState +// import dagger.hilt.android.AndroidEntryPoint +// import im.vector.app.core.extensions.cleanup +// import im.vector.app.core.extensions.configureWith +// import im.vector.app.core.platform.VectorBaseFragment +// import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel +// import javax.inject.Inject +// +// @AndroidEntryPoint +// class VerificationNotMeFragment : +// VectorBaseFragment(), +// VerificationNotMeController.Listener { +// +// @Inject lateinit var controller: VerificationNotMeController +// +// private val viewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) +// +// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { +// return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// setupRecyclerView() +// } +// +// override fun onDestroyView() { +// views.bottomSheetVerificationRecyclerView.cleanup() +// controller.listener = null +// super.onDestroyView() +// } +// +// private fun setupRecyclerView() { +// views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) +// controller.listener = this +// } +// +// override fun invalidate() = withState(viewModel) { state -> +// controller.update(state) +// } +// +// override fun onTapSkip() { +// viewModel.continueFromWasNotMe() +// } +// +// override fun onTapSettings() { +// viewModel.goToSettings() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt index f2a0a7d7e9..e3aaf0dc9c 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt @@ -1,147 +1,147 @@ -/* - * Copyright 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.choose - -import com.airbnb.epoxy.EpoxyController -import im.vector.app.R -import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider -import im.vector.app.core.ui.list.buttonPositiveDestructiveButtonBarItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationQrCodeItem -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence -import javax.inject.Inject - -class VerificationChooseMethodController @Inject constructor( - private val stringProvider: StringProvider, - private val colorProvider: ColorProvider -) : EpoxyController() { - - var listener: Listener? = null - - private var viewState: VerificationChooseMethodViewState? = null - - fun update(viewState: VerificationChooseMethodViewState) { - this.viewState = viewState - requestModelBuild() - } - - override fun buildModels() { - val state = viewState ?: return - val host = this - - if (state.otherCanScanQrCode || state.otherCanShowQrCode) { - val scanCodeInstructions: String - val scanOtherCodeTitle: String - val compareEmojiSubtitle: String - if (state.isMe) { - scanCodeInstructions = stringProvider.getString(R.string.verification_scan_self_notice) - scanOtherCodeTitle = stringProvider.getString(R.string.verification_scan_with_this_device) - compareEmojiSubtitle = stringProvider.getString(R.string.verification_scan_self_emoji_subtitle) - } else { - scanCodeInstructions = stringProvider.getString(R.string.verification_scan_notice) - scanOtherCodeTitle = stringProvider.getString(R.string.verification_scan_their_code) - compareEmojiSubtitle = stringProvider.getString(R.string.verification_scan_emoji_subtitle) - } - - bottomSheetVerificationNoticeItem { - id("notice") - notice(scanCodeInstructions.toEpoxyCharSequence()) - } - - if (state.otherCanScanQrCode && !state.qrCodeText.isNullOrBlank()) { - bottomSheetVerificationQrCodeItem { - id("qr") - data(state.qrCodeText) - } - - bottomSheetDividerItem { - id("sep0") - } - } - - if (state.otherCanShowQrCode) { - bottomSheetVerificationActionItem { - id("openCamera") - title(scanOtherCodeTitle) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - iconRes(R.drawable.ic_camera) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - listener { host.listener?.openCamera() } - } - - bottomSheetDividerItem { - id("sep1") - } - } - - bottomSheetVerificationActionItem { - id("openEmoji") - title(host.stringProvider.getString(R.string.verification_scan_emoji_title)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - subTitle(compareEmojiSubtitle) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.doVerifyBySas() } - } - } else if (state.sasModeAvailable) { - bottomSheetVerificationActionItem { - id("openEmoji") - title(host.stringProvider.getString(R.string.verification_no_scan_emoji_title)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.doVerifyBySas() } - } - } else if (!state.isReadySent) { - // a bit of a special case, if you tapped on the timeline cell but not on a button - buttonPositiveDestructiveButtonBarItem { - id("accept_decline") - positiveText(host.stringProvider.getString(R.string.action_accept).toEpoxyCharSequence()) - destructiveText(host.stringProvider.getString(R.string.action_decline).toEpoxyCharSequence()) - positiveButtonClickAction { host.listener?.acceptRequest() } - destructiveButtonClickAction { host.listener?.declineRequest() } - } - } - - if (state.isMe && state.canCrossSign) { - bottomSheetDividerItem { - id("sep_notMe") - } - - bottomSheetVerificationActionItem { - id("wasnote") - title(host.stringProvider.getString(R.string.verify_new_session_was_not_me)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.onClickOnWasNotMe() } - } - } - } - - interface Listener { - fun openCamera() - fun doVerifyBySas() - fun onClickOnWasNotMe() - fun acceptRequest() - fun declineRequest() - } -} +// /* +// * Copyright 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.choose +// +// import com.airbnb.epoxy.EpoxyController +// import im.vector.app.R +// import im.vector.app.core.epoxy.bottomSheetDividerItem +// import im.vector.app.core.resources.ColorProvider +// import im.vector.app.core.resources.StringProvider +// import im.vector.app.core.ui.list.buttonPositiveDestructiveButtonBarItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationQrCodeItem +// import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +// import javax.inject.Inject +// +// class VerificationChooseMethodController @Inject constructor( +// private val stringProvider: StringProvider, +// private val colorProvider: ColorProvider +// ) : EpoxyController() { +// +// var listener: Listener? = null +// +// private var viewState: VerificationChooseMethodViewState? = null +// +// fun update(viewState: VerificationChooseMethodViewState) { +// this.viewState = viewState +// requestModelBuild() +// } +// +// override fun buildModels() { +// val state = viewState ?: return +// val host = this +// +// if (state.otherCanScanQrCode || state.otherCanShowQrCode) { +// val scanCodeInstructions: String +// val scanOtherCodeTitle: String +// val compareEmojiSubtitle: String +// if (state.isMe) { +// scanCodeInstructions = stringProvider.getString(R.string.verification_scan_self_notice) +// scanOtherCodeTitle = stringProvider.getString(R.string.verification_scan_with_this_device) +// compareEmojiSubtitle = stringProvider.getString(R.string.verification_scan_self_emoji_subtitle) +// } else { +// scanCodeInstructions = stringProvider.getString(R.string.verification_scan_notice) +// scanOtherCodeTitle = stringProvider.getString(R.string.verification_scan_their_code) +// compareEmojiSubtitle = stringProvider.getString(R.string.verification_scan_emoji_subtitle) +// } +// +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(scanCodeInstructions.toEpoxyCharSequence()) +// } +// +// if (state.otherCanScanQrCode && !state.qrCodeText.isNullOrBlank()) { +// bottomSheetVerificationQrCodeItem { +// id("qr") +// data(state.qrCodeText) +// } +// +// bottomSheetDividerItem { +// id("sep0") +// } +// } +// +// if (state.otherCanShowQrCode) { +// bottomSheetVerificationActionItem { +// id("openCamera") +// title(scanOtherCodeTitle) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// iconRes(R.drawable.ic_camera) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// listener { host.listener?.openCamera() } +// } +// +// bottomSheetDividerItem { +// id("sep1") +// } +// } +// +// bottomSheetVerificationActionItem { +// id("openEmoji") +// title(host.stringProvider.getString(R.string.verification_scan_emoji_title)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// subTitle(compareEmojiSubtitle) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.doVerifyBySas() } +// } +// } else if (state.sasModeAvailable) { +// bottomSheetVerificationActionItem { +// id("openEmoji") +// title(host.stringProvider.getString(R.string.verification_no_scan_emoji_title)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.doVerifyBySas() } +// } +// } else if (!state.isReadySent) { +// // a bit of a special case, if you tapped on the timeline cell but not on a button +// buttonPositiveDestructiveButtonBarItem { +// id("accept_decline") +// positiveText(host.stringProvider.getString(R.string.action_accept).toEpoxyCharSequence()) +// destructiveText(host.stringProvider.getString(R.string.action_decline).toEpoxyCharSequence()) +// positiveButtonClickAction { host.listener?.acceptRequest() } +// destructiveButtonClickAction { host.listener?.declineRequest() } +// } +// } +// +// if (state.isMe && state.canCrossSign) { +// bottomSheetDividerItem { +// id("sep_notMe") +// } +// +// bottomSheetVerificationActionItem { +// id("wasnote") +// title(host.stringProvider.getString(R.string.verify_new_session_was_not_me)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.onClickOnWasNotMe() } +// } +// } +// } +// +// interface Listener { +// fun openCamera() +// fun doVerifyBySas() +// fun onClickOnWasNotMe() +// fun acceptRequest() +// fun declineRequest() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodFragment.kt index 6aa5d2df8c..a187dda48d 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodFragment.kt @@ -1,136 +1,136 @@ -/* - * 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.choose - -import android.app.Activity -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.airbnb.mvrx.fragmentViewModel -import com.airbnb.mvrx.parentFragmentViewModel -import com.airbnb.mvrx.withState -import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R -import im.vector.app.core.extensions.cleanup -import im.vector.app.core.extensions.configureWith -import im.vector.app.core.extensions.registerStartForActivityResult -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO -import im.vector.app.core.utils.checkPermissions -import im.vector.app.core.utils.onPermissionDeniedDialog -import im.vector.app.core.utils.registerForPermissionsResult -import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding -import im.vector.app.features.crypto.verification.VerificationAction -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import im.vector.app.features.qrcode.QrCodeScannerActivity -import timber.log.Timber -import javax.inject.Inject - -@AndroidEntryPoint -class VerificationChooseMethodFragment : - VectorBaseFragment(), - VerificationChooseMethodController.Listener { - - @Inject lateinit var controller: VerificationChooseMethodController - private val viewModel by fragmentViewModel(VerificationChooseMethodViewModel::class) - - private val sharedViewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { - return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - setupRecyclerView() - } - - override fun onDestroyView() { - views.bottomSheetVerificationRecyclerView.cleanup() - controller.listener = null - super.onDestroyView() - } - - private fun setupRecyclerView() { - views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) - controller.listener = this - } - - override fun invalidate() = withState(viewModel) { state -> - controller.update(state) - } - - override fun doVerifyBySas() = withState(sharedViewModel) { state -> - sharedViewModel.handle( - VerificationAction.StartSASVerification - ) - } - - private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently -> - if (allGranted) { - doOpenQRCodeScanner() - } else if (deniedPermanently) { - activity?.onPermissionDeniedDialog(R.string.denied_permission_camera) - } - } - - override fun openCamera() { - if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), openCameraActivityResultLauncher)) { - doOpenQRCodeScanner() - } - } - - override fun onClickOnWasNotMe() { - sharedViewModel.itWasNotMe() - } - - override fun acceptRequest() { - sharedViewModel.handle(VerificationAction.ReadyPendingVerification) - } - - override fun declineRequest() { - sharedViewModel.handle(VerificationAction.CancelPendingVerification) - } - - private fun doOpenQRCodeScanner() { - QrCodeScannerActivity.startForResult(requireActivity(), scanActivityResultLauncher) - } - - private val scanActivityResultLauncher = registerStartForActivityResult { activityResult -> - if (activityResult.resultCode == Activity.RESULT_OK) { - val scannedQrCode = QrCodeScannerActivity.getResultText(activityResult.data) - val wasQrCode = QrCodeScannerActivity.getResultIsQrCode(activityResult.data) - - if (wasQrCode && !scannedQrCode.isNullOrBlank()) { - onRemoteQrCodeScanned(scannedQrCode) - } else { - Timber.w("It was not a QR code, or empty result") - } - } - } - - private fun onRemoteQrCodeScanned(remoteQrCode: String) = withState(sharedViewModel) { state -> - sharedViewModel.handle( - VerificationAction.RemoteQrCodeScanned( - state.otherUserId, - state.pendingRequest.invoke()?.transactionId ?: "", - remoteQrCode - ) - ) - } -} +// /* +// * 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.choose +// +// import android.app.Activity +// import android.os.Bundle +// import android.view.LayoutInflater +// import android.view.View +// import android.view.ViewGroup +// import com.airbnb.mvrx.fragmentViewModel +// import com.airbnb.mvrx.parentFragmentViewModel +// import com.airbnb.mvrx.withState +// import dagger.hilt.android.AndroidEntryPoint +// import im.vector.app.R +// import im.vector.app.core.extensions.cleanup +// import im.vector.app.core.extensions.configureWith +// import im.vector.app.core.extensions.registerStartForActivityResult +// import im.vector.app.core.platform.VectorBaseFragment +// import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO +// import im.vector.app.core.utils.checkPermissions +// import im.vector.app.core.utils.onPermissionDeniedDialog +// import im.vector.app.core.utils.registerForPermissionsResult +// import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding +// import im.vector.app.features.crypto.verification.VerificationAction +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel +// import im.vector.app.features.qrcode.QrCodeScannerActivity +// import timber.log.Timber +// import javax.inject.Inject +// +// @AndroidEntryPoint +// class VerificationChooseMethodFragment : +// VectorBaseFragment(), +// VerificationChooseMethodController.Listener { +// +// @Inject lateinit var controller: VerificationChooseMethodController +// private val viewModel by fragmentViewModel(VerificationChooseMethodViewModel::class) +// +// private val sharedViewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) +// +// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { +// return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// +// setupRecyclerView() +// } +// +// override fun onDestroyView() { +// views.bottomSheetVerificationRecyclerView.cleanup() +// controller.listener = null +// super.onDestroyView() +// } +// +// private fun setupRecyclerView() { +// views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) +// controller.listener = this +// } +// +// override fun invalidate() = withState(viewModel) { state -> +// controller.update(state) +// } +// +// override fun doVerifyBySas() = withState(sharedViewModel) { state -> +// sharedViewModel.handle( +// VerificationAction.StartSASVerification +// ) +// } +// +// private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently -> +// if (allGranted) { +// doOpenQRCodeScanner() +// } else if (deniedPermanently) { +// activity?.onPermissionDeniedDialog(R.string.denied_permission_camera) +// } +// } +// +// override fun openCamera() { +// if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), openCameraActivityResultLauncher)) { +// doOpenQRCodeScanner() +// } +// } +// +// override fun onClickOnWasNotMe() { +// sharedViewModel.itWasNotMe() +// } +// +// override fun acceptRequest() { +// sharedViewModel.handle(VerificationAction.ReadyPendingVerification) +// } +// +// override fun declineRequest() { +// sharedViewModel.handle(VerificationAction.CancelPendingVerification) +// } +// +// private fun doOpenQRCodeScanner() { +// QrCodeScannerActivity.startForResult(requireActivity(), scanActivityResultLauncher) +// } +// +// private val scanActivityResultLauncher = registerStartForActivityResult { activityResult -> +// if (activityResult.resultCode == Activity.RESULT_OK) { +// val scannedQrCode = QrCodeScannerActivity.getResultText(activityResult.data) +// val wasQrCode = QrCodeScannerActivity.getResultIsQrCode(activityResult.data) +// +// if (wasQrCode && !scannedQrCode.isNullOrBlank()) { +// onRemoteQrCodeScanned(scannedQrCode) +// } else { +// Timber.w("It was not a QR code, or empty result") +// } +// } +// } +// +// private fun onRemoteQrCodeScanned(remoteQrCode: String) = withState(sharedViewModel) { state -> +// sharedViewModel.handle( +// VerificationAction.RemoteQrCodeScanned( +// state.otherUserId, +// state.pendingRequest.invoke()?.transactionId ?: "", +// remoteQrCode +// ) +// ) +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodViewModel.kt index 847bec08a0..1dbfde307a 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodViewModel.kt @@ -1,172 +1,172 @@ -/* - * 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.choose - -import com.airbnb.mvrx.MavericksState -import com.airbnb.mvrx.MavericksViewModelFactory -import com.airbnb.mvrx.ViewModelContext -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import dagger.hilt.EntryPoints -import im.vector.app.core.di.MavericksAssistedViewModelFactory -import im.vector.app.core.di.SingletonEntryPoint -import im.vector.app.core.di.hiltMavericksViewModelFactory -import im.vector.app.core.platform.EmptyAction -import im.vector.app.core.platform.EmptyViewEvents -import im.vector.app.core.platform.VectorViewModel -import im.vector.app.features.crypto.verification.VerificationBottomSheet -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState -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.VerificationEvent -import org.matrix.android.sdk.api.session.crypto.verification.VerificationService -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction - -data class VerificationChooseMethodViewState( - val otherUserId: String = "", - val transactionId: String = "", - val otherCanShowQrCode: Boolean = false, - val otherCanScanQrCode: Boolean = false, - val qrCodeText: String? = null, - val sasModeAvailable: Boolean = false, - val isMe: Boolean = false, - val canCrossSign: Boolean = false, - val isReadySent: Boolean = false -) : MavericksState - -class VerificationChooseMethodViewModel @AssistedInject constructor( - @Assisted initialState: VerificationChooseMethodViewState, - private val session: Session -) : VectorViewModel(initialState), VerificationService.Listener { - - init { -// session.cryptoService().verificationService().addListener(this) - - session.cryptoService().verificationService() - .requestEventFlow() - .onEach { - when (it) { - // TODO check transaction id - is VerificationEvent.RequestAdded -> verificationRequestCreated(it.request) - is VerificationEvent.RequestUpdated -> verificationRequestUpdated(it.request) - is VerificationEvent.TransactionAdded -> transactionCreated(it.transaction) - is VerificationEvent.TransactionUpdated -> transactionUpdated(it.transaction) - } - } - .launchIn(viewModelScope) - - viewModelScope.launch { - - val verificationService = session.cryptoService().verificationService() - val pvr = verificationService.getExistingVerificationRequest(initialState.otherUserId, initialState.transactionId) - - // Get the QR code now, because transaction is already created, so transactionCreated() will not be called - val qrCodeVerificationTransaction = verificationService.getExistingTransaction(initialState.otherUserId, initialState.transactionId) - - setState { - VerificationChooseMethodViewState( - otherUserId = initialState.otherUserId, - isMe = session.myUserId == pvr?.otherUserId, - canCrossSign = session.cryptoService().crossSigningService().canCrossSign(), - transactionId = pvr?.transactionId ?: initialState.transactionId, - otherCanShowQrCode = pvr?.otherCanShowQrCode.orFalse(), - otherCanScanQrCode = pvr?.otherCanScanQrCode.orFalse(), - qrCodeText = pvr?.qrCodeText, - sasModeAvailable = pvr?.isSasSupported.orFalse(), - isReadySent = pvr?.state == EVerificationState.Ready - ) - } - } - - - } - - override fun transactionCreated(tx: VerificationTransaction) { - transactionUpdated(tx) - } - - override fun transactionUpdated(tx: VerificationTransaction) = withState { state -> -// if (tx.transactionId == state.transactionId && tx is QrCodeVerificationTransaction) { +// /* +// * 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.choose +// +// import com.airbnb.mvrx.MavericksState +// import com.airbnb.mvrx.MavericksViewModelFactory +// import com.airbnb.mvrx.ViewModelContext +// import dagger.assisted.Assisted +// import dagger.assisted.AssistedFactory +// import dagger.assisted.AssistedInject +// import dagger.hilt.EntryPoints +// import im.vector.app.core.di.MavericksAssistedViewModelFactory +// import im.vector.app.core.di.SingletonEntryPoint +// import im.vector.app.core.di.hiltMavericksViewModelFactory +// import im.vector.app.core.platform.EmptyAction +// import im.vector.app.core.platform.EmptyViewEvents +// import im.vector.app.core.platform.VectorViewModel +// import im.vector.app.features.crypto.verification.VerificationBottomSheet +// import kotlinx.coroutines.flow.launchIn +// import kotlinx.coroutines.flow.onEach +// import kotlinx.coroutines.launch +// import org.matrix.android.sdk.api.extensions.orFalse +// import org.matrix.android.sdk.api.session.Session +// import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState +// 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.VerificationEvent +// import org.matrix.android.sdk.api.session.crypto.verification.VerificationService +// import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction +// +// data class VerificationChooseMethodViewState( +// val otherUserId: String = "", +// val transactionId: String = "", +// val otherCanShowQrCode: Boolean = false, +// val otherCanScanQrCode: Boolean = false, +// val qrCodeText: String? = null, +// val sasModeAvailable: Boolean = false, +// val isMe: Boolean = false, +// val canCrossSign: Boolean = false, +// val isReadySent: Boolean = false +// ) : MavericksState +// +// class VerificationChooseMethodViewModel @AssistedInject constructor( +// @Assisted initialState: VerificationChooseMethodViewState, +// private val session: Session +// ) : VectorViewModel(initialState), VerificationService.Listener { +// +// init { +// // session.cryptoService().verificationService().addListener(this) +// +// session.cryptoService().verificationService() +// .requestEventFlow() +// .onEach { +// when (it) { +// // TODO check transaction id +// is VerificationEvent.RequestAdded -> verificationRequestCreated(it.request) +// is VerificationEvent.RequestUpdated -> verificationRequestUpdated(it.request) +// is VerificationEvent.TransactionAdded -> transactionCreated(it.transaction) +// is VerificationEvent.TransactionUpdated -> transactionUpdated(it.transaction) +// } +// } +// .launchIn(viewModelScope) +// +// viewModelScope.launch { +// +// val verificationService = session.cryptoService().verificationService() +// val pvr = verificationService.getExistingVerificationRequest(initialState.otherUserId, initialState.transactionId) +// +// // Get the QR code now, because transaction is already created, so transactionCreated() will not be called +// val qrCodeVerificationTransaction = verificationService.getExistingTransaction(initialState.otherUserId, initialState.transactionId) +// // setState { -// copy( -// qrCodeText = tx.qrCodeText +// VerificationChooseMethodViewState( +// otherUserId = initialState.otherUserId, +// isMe = session.myUserId == pvr?.otherUserId, +// canCrossSign = session.cryptoService().crossSigningService().canCrossSign(), +// transactionId = pvr?.transactionId ?: initialState.transactionId, +// otherCanShowQrCode = pvr?.otherCanShowQrCode.orFalse(), +// otherCanScanQrCode = pvr?.otherCanScanQrCode.orFalse(), +// qrCodeText = pvr?.qrCodeText, +// sasModeAvailable = pvr?.isSasSupported.orFalse(), +// isReadySent = pvr?.state == EVerificationState.Ready // ) // } // } - } - - override fun verificationRequestCreated(pr: PendingVerificationRequest) { - verificationRequestUpdated(pr) - } - - override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state -> - viewModelScope.launch { - val pvr = session.cryptoService().verificationService().getExistingVerificationRequest(state.otherUserId, state.transactionId) - - setState { - copy( - otherCanShowQrCode = pvr?.otherCanShowQrCode.orFalse(), - otherCanScanQrCode = pvr?.otherCanScanQrCode.orFalse(), - sasModeAvailable = pvr?.isSasSupported.orFalse(), - isReadySent = pvr?.state == EVerificationState.Ready, - qrCodeText = pvr?.qrCodeText - ) - } - } - } - - @AssistedFactory - interface Factory : MavericksAssistedViewModelFactory { - override fun create(initialState: VerificationChooseMethodViewState): VerificationChooseMethodViewModel - } - - companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() { - - override fun initialState(viewModelContext: ViewModelContext): VerificationChooseMethodViewState { - val args: VerificationBottomSheet.VerificationArgs = viewModelContext.args() - val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession() - val verificationService = session.cryptoService().verificationService() -// val pvr = verificationService.getExistingVerificationRequest(args.otherUserId, args.verificationId) - - // Get the QR code now, because transaction is already created, so transactionCreated() will not be called -// val qrCodeVerificationTransaction = verificationService.getExistingTransaction(args.otherUserId, args.verificationId ?: "") - - return VerificationChooseMethodViewState( - otherUserId = args.otherUserId, -// isMe = session.myUserId == pvr?.otherUserId, - canCrossSign = session.cryptoService().crossSigningService().canCrossSign(), - transactionId = args.verificationId ?: "", -// otherCanShowQrCode = pvr?.otherCanShowQrCode().orFalse(), -// otherCanScanQrCode = pvr?.otherCanScanQrCode().orFalse(), -// qrCodeText = (qrCodeVerificationTransaction as? QrCodeVerificationTransaction)?.qrCodeText, -// sasModeAvailable = pvr?.isSasSupported().orFalse() - ) - } - } - - override fun onCleared() { -// session.cryptoService().verificationService().removeListener(this) - super.onCleared() - } - - override fun handle(action: EmptyAction) {} -} +// +// +// } +// +// override fun transactionCreated(tx: VerificationTransaction) { +// transactionUpdated(tx) +// } +// +// override fun transactionUpdated(tx: VerificationTransaction) = withState { state -> +// // if (tx.transactionId == state.transactionId && tx is QrCodeVerificationTransaction) { +// // setState { +// // copy( +// // qrCodeText = tx.qrCodeText +// // ) +// // } +// // } +// } +// +// override fun verificationRequestCreated(pr: PendingVerificationRequest) { +// verificationRequestUpdated(pr) +// } +// +// override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state -> +// viewModelScope.launch { +// val pvr = session.cryptoService().verificationService().getExistingVerificationRequest(state.otherUserId, state.transactionId) +// +// setState { +// copy( +// otherCanShowQrCode = pvr?.otherCanShowQrCode.orFalse(), +// otherCanScanQrCode = pvr?.otherCanScanQrCode.orFalse(), +// sasModeAvailable = pvr?.isSasSupported.orFalse(), +// isReadySent = pvr?.state == EVerificationState.Ready, +// qrCodeText = pvr?.qrCodeText +// ) +// } +// } +// } +// +// @AssistedFactory +// interface Factory : MavericksAssistedViewModelFactory { +// override fun create(initialState: VerificationChooseMethodViewState): VerificationChooseMethodViewModel +// } +// +// companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() { +// +// override fun initialState(viewModelContext: ViewModelContext): VerificationChooseMethodViewState { +// val args: VerificationBottomSheet.VerificationArgs = viewModelContext.args() +// val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession() +// val verificationService = session.cryptoService().verificationService() +// // val pvr = verificationService.getExistingVerificationRequest(args.otherUserId, args.verificationId) +// +// // Get the QR code now, because transaction is already created, so transactionCreated() will not be called +// // val qrCodeVerificationTransaction = verificationService.getExistingTransaction(args.otherUserId, args.verificationId ?: "") +// +// return VerificationChooseMethodViewState( +// otherUserId = args.otherUserId, +// // isMe = session.myUserId == pvr?.otherUserId, +// canCrossSign = session.cryptoService().crossSigningService().canCrossSign(), +// transactionId = args.verificationId ?: "", +// // otherCanShowQrCode = pvr?.otherCanShowQrCode().orFalse(), +// // otherCanScanQrCode = pvr?.otherCanScanQrCode().orFalse(), +// // qrCodeText = (qrCodeVerificationTransaction as? QrCodeVerificationTransaction)?.qrCodeText, +// // sasModeAvailable = pvr?.isSasSupported().orFalse() +// ) +// } +// } +// +// override fun onCleared() { +// // session.cryptoService().verificationService().removeListener(this) +// super.onCleared() +// } +// +// override fun handle(action: EmptyAction) {} +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt index 7bd0e393eb..0eda50cecf 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt @@ -1,143 +1,143 @@ -/* - * Copyright 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.conclusion - -import com.airbnb.epoxy.EpoxyController -import im.vector.app.R -import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem -import im.vector.app.features.html.EventHtmlRenderer -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence -import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel -import javax.inject.Inject - -class VerificationConclusionController @Inject constructor( - private val stringProvider: StringProvider, - private val colorProvider: ColorProvider, - private val eventHtmlRenderer: EventHtmlRenderer -) : EpoxyController() { - - var listener: Listener? = null - - private var viewState: VerificationConclusionViewState? = null - - fun update(viewState: VerificationConclusionViewState) { - this.viewState = viewState - requestModelBuild() - } - - override fun buildModels() { - val state = viewState ?: return - val host = this - - when (state.conclusionState) { - ConclusionState.SUCCESS -> { - bottomSheetVerificationNoticeItem { - id("notice") - notice( - host.stringProvider.getString( - if (state.isSelfVerification) R.string.verification_conclusion_ok_self_notice - else R.string.verification_conclusion_ok_notice - ) - .toEpoxyCharSequence() - ) - } - - bottomSheetVerificationBigImageItem { - id("image") - roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Trusted) - } - - bottomDone() - } - ConclusionState.WARNING -> { - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.stringProvider.getString(R.string.verification_conclusion_not_secure).toEpoxyCharSequence()) - } - - bottomSheetVerificationBigImageItem { - id("image") - roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Warning) - } - - bottomSheetVerificationNoticeItem { - id("warning_notice") - notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verification_conclusion_compromised)).toEpoxyCharSequence()) - } - - bottomGotIt() - } - ConclusionState.INVALID_QR_CODE -> { - bottomSheetVerificationNoticeItem { - id("invalid_qr") - notice(host.stringProvider.getString(R.string.verify_invalid_qr_notice).toEpoxyCharSequence()) - } - - bottomGotIt() - } - ConclusionState.CANCELLED -> { - bottomSheetVerificationNoticeItem { - id("notice_cancelled") - notice(host.stringProvider.getString(R.string.verify_cancelled_notice).toEpoxyCharSequence()) - } - - bottomGotIt() - } - } - } - - private fun bottomDone() { - val host = this - bottomSheetDividerItem { - id("sep0") - } - - bottomSheetVerificationActionItem { - id("done") - title(host.stringProvider.getString(R.string.done)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.onButtonTapped(true) } - } - } - - private fun bottomGotIt() { - val host = this - bottomSheetDividerItem { - id("sep0") - } - - bottomSheetVerificationActionItem { - id("got_it") - title(host.stringProvider.getString(R.string.sas_got_it)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.onButtonTapped(false) } - } - } - - interface Listener { - fun onButtonTapped(success: Boolean) - } -} +// /* +// * Copyright 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.conclusion +// +// import com.airbnb.epoxy.EpoxyController +// import im.vector.app.R +// import im.vector.app.core.epoxy.bottomSheetDividerItem +// import im.vector.app.core.resources.ColorProvider +// import im.vector.app.core.resources.StringProvider +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +// import im.vector.app.features.html.EventHtmlRenderer +// import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +// import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +// import javax.inject.Inject +// +// class VerificationConclusionController @Inject constructor( +// private val stringProvider: StringProvider, +// private val colorProvider: ColorProvider, +// private val eventHtmlRenderer: EventHtmlRenderer +// ) : EpoxyController() { +// +// var listener: Listener? = null +// +// private var viewState: VerificationConclusionViewState? = null +// +// fun update(viewState: VerificationConclusionViewState) { +// this.viewState = viewState +// requestModelBuild() +// } +// +// override fun buildModels() { +// val state = viewState ?: return +// val host = this +// +// when (state.conclusionState) { +// ConclusionState.SUCCESS -> { +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice( +// host.stringProvider.getString( +// if (state.isSelfVerification) R.string.verification_conclusion_ok_self_notice +// else R.string.verification_conclusion_ok_notice +// ) +// .toEpoxyCharSequence() +// ) +// } +// +// bottomSheetVerificationBigImageItem { +// id("image") +// roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Trusted) +// } +// +// bottomDone() +// } +// ConclusionState.WARNING -> { +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.stringProvider.getString(R.string.verification_conclusion_not_secure).toEpoxyCharSequence()) +// } +// +// bottomSheetVerificationBigImageItem { +// id("image") +// roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Warning) +// } +// +// bottomSheetVerificationNoticeItem { +// id("warning_notice") +// notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verification_conclusion_compromised)).toEpoxyCharSequence()) +// } +// +// bottomGotIt() +// } +// ConclusionState.INVALID_QR_CODE -> { +// bottomSheetVerificationNoticeItem { +// id("invalid_qr") +// notice(host.stringProvider.getString(R.string.verify_invalid_qr_notice).toEpoxyCharSequence()) +// } +// +// bottomGotIt() +// } +// ConclusionState.CANCELLED -> { +// bottomSheetVerificationNoticeItem { +// id("notice_cancelled") +// notice(host.stringProvider.getString(R.string.verify_cancelled_notice).toEpoxyCharSequence()) +// } +// +// bottomGotIt() +// } +// } +// } +// +// private fun bottomDone() { +// val host = this +// bottomSheetDividerItem { +// id("sep0") +// } +// +// bottomSheetVerificationActionItem { +// id("done") +// title(host.stringProvider.getString(R.string.done)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.onButtonTapped(true) } +// } +// } +// +// private fun bottomGotIt() { +// val host = this +// bottomSheetDividerItem { +// id("sep0") +// } +// +// bottomSheetVerificationActionItem { +// id("got_it") +// title(host.stringProvider.getString(R.string.sas_got_it)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.onButtonTapped(false) } +// } +// } +// +// interface Listener { +// fun onButtonTapped(success: Boolean) +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionFragment.kt index dd559e8a1b..a373efaa4c 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionFragment.kt @@ -1,82 +1,82 @@ -/* - * 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.conclusion - -import android.os.Bundle -import android.os.Parcelable -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.airbnb.mvrx.fragmentViewModel -import com.airbnb.mvrx.parentFragmentViewModel -import com.airbnb.mvrx.withState -import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.core.extensions.cleanup -import im.vector.app.core.extensions.configureWith -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding -import im.vector.app.features.crypto.verification.VerificationAction -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import kotlinx.parcelize.Parcelize -import javax.inject.Inject - -@AndroidEntryPoint -class VerificationConclusionFragment : - VectorBaseFragment(), - VerificationConclusionController.Listener { - - @Inject lateinit var controller: VerificationConclusionController - - @Parcelize - data class Args( - val isSuccessFull: Boolean, - val cancelReason: String?, - val isMe: Boolean - ) : Parcelable - - private val sharedViewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) - - private val viewModel by fragmentViewModel(VerificationConclusionViewModel::class) - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { - return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - setupRecyclerView() - } - - override fun onDestroyView() { - views.bottomSheetVerificationRecyclerView.cleanup() - controller.listener = null - super.onDestroyView() - } - - private fun setupRecyclerView() { - views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) - controller.listener = this - } - - override fun invalidate() = withState(viewModel) { state -> - controller.update(state) - } - - override fun onButtonTapped(success: Boolean) { - sharedViewModel.handle(VerificationAction.GotItConclusion(success)) - } -} +// /* +// * 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.conclusion +// +// import android.os.Bundle +// import android.os.Parcelable +// import android.view.LayoutInflater +// import android.view.View +// import android.view.ViewGroup +// import com.airbnb.mvrx.fragmentViewModel +// import com.airbnb.mvrx.parentFragmentViewModel +// import com.airbnb.mvrx.withState +// import dagger.hilt.android.AndroidEntryPoint +// import im.vector.app.core.extensions.cleanup +// import im.vector.app.core.extensions.configureWith +// import im.vector.app.core.platform.VectorBaseFragment +// import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding +// import im.vector.app.features.crypto.verification.VerificationAction +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel +// import kotlinx.parcelize.Parcelize +// import javax.inject.Inject +// +// @AndroidEntryPoint +// class VerificationConclusionFragment : +// VectorBaseFragment(), +// VerificationConclusionController.Listener { +// +// @Inject lateinit var controller: VerificationConclusionController +// +// @Parcelize +// data class Args( +// val isSuccessFull: Boolean, +// val cancelReason: String?, +// val isMe: Boolean +// ) : Parcelable +// +// private val sharedViewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) +// +// private val viewModel by fragmentViewModel(VerificationConclusionViewModel::class) +// +// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { +// return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// +// setupRecyclerView() +// } +// +// override fun onDestroyView() { +// views.bottomSheetVerificationRecyclerView.cleanup() +// controller.listener = null +// super.onDestroyView() +// } +// +// private fun setupRecyclerView() { +// views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) +// controller.listener = this +// } +// +// override fun invalidate() = withState(viewModel) { state -> +// controller.update(state) +// } +// +// override fun onButtonTapped(success: Boolean) { +// sharedViewModel.handle(VerificationAction.GotItConclusion(success)) +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionViewModel.kt index 8883ffb94e..c43655e81d 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionViewModel.kt @@ -1,68 +1,68 @@ -/* - * 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.conclusion - -import com.airbnb.mvrx.MavericksState -import com.airbnb.mvrx.MavericksViewModelFactory -import com.airbnb.mvrx.ViewModelContext -import im.vector.app.core.platform.EmptyAction -import im.vector.app.core.platform.EmptyViewEvents -import im.vector.app.core.platform.VectorViewModel -import org.matrix.android.sdk.api.session.crypto.verification.CancelCode -import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf - -data class VerificationConclusionViewState( - val conclusionState: ConclusionState = ConclusionState.CANCELLED, - val isSelfVerification: Boolean = false -) : MavericksState - -enum class ConclusionState { - SUCCESS, - WARNING, - CANCELLED, - INVALID_QR_CODE -} - -class VerificationConclusionViewModel(initialState: VerificationConclusionViewState) : - VectorViewModel(initialState) { - - companion object : MavericksViewModelFactory { - - override fun initialState(viewModelContext: ViewModelContext): VerificationConclusionViewState? { - val args = viewModelContext.args() - - return when (safeValueOf(args.cancelReason)) { - CancelCode.QrCodeInvalid -> { - VerificationConclusionViewState(ConclusionState.INVALID_QR_CODE, args.isMe) - } - CancelCode.MismatchedUser, - CancelCode.MismatchedSas, - CancelCode.MismatchedCommitment, - CancelCode.MismatchedKeys -> { - VerificationConclusionViewState(ConclusionState.WARNING, args.isMe) - } - else -> { - VerificationConclusionViewState( - if (args.isSuccessFull) ConclusionState.SUCCESS else ConclusionState.CANCELLED, - args.isMe - ) - } - } - } - } - - override fun handle(action: EmptyAction) {} -} +// /* +// * 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.conclusion +// +// import com.airbnb.mvrx.MavericksState +// import com.airbnb.mvrx.MavericksViewModelFactory +// import com.airbnb.mvrx.ViewModelContext +// import im.vector.app.core.platform.EmptyAction +// import im.vector.app.core.platform.EmptyViewEvents +// import im.vector.app.core.platform.VectorViewModel +// import org.matrix.android.sdk.api.session.crypto.verification.CancelCode +// import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf +// +// data class VerificationConclusionViewState( +// val conclusionState: ConclusionState = ConclusionState.CANCELLED, +// val isSelfVerification: Boolean = false +// ) : MavericksState +// +// enum class ConclusionState { +// SUCCESS, +// WARNING, +// CANCELLED, +// INVALID_QR_CODE +// } +// +// class VerificationConclusionViewModel(initialState: VerificationConclusionViewState) : +// VectorViewModel(initialState) { +// +// companion object : MavericksViewModelFactory { +// +// override fun initialState(viewModelContext: ViewModelContext): VerificationConclusionViewState? { +// val args = viewModelContext.args() +// +// return when (safeValueOf(args.cancelReason)) { +// CancelCode.QrCodeInvalid -> { +// VerificationConclusionViewState(ConclusionState.INVALID_QR_CODE, args.isMe) +// } +// CancelCode.MismatchedUser, +// CancelCode.MismatchedSas, +// CancelCode.MismatchedCommitment, +// CancelCode.MismatchedKeys -> { +// VerificationConclusionViewState(ConclusionState.WARNING, args.isMe) +// } +// else -> { +// VerificationConclusionViewState( +// if (args.isSuccessFull) ConclusionState.SUCCESS else ConclusionState.CANCELLED, +// args.isMe +// ) +// } +// } +// } +// } +// +// override fun handle(action: EmptyAction) {} +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt index bf514249d8..aa0d9a71dc 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt @@ -1,168 +1,168 @@ -/* - * Copyright 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.emoji - -import com.airbnb.epoxy.EpoxyController -import com.airbnb.mvrx.Fail -import com.airbnb.mvrx.Success -import im.vector.app.R -import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.epoxy.errorWithRetryItem -import im.vector.app.core.error.ErrorFormatter -import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationDecimalCodeItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationEmojisItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem -import im.vector.app.features.displayname.getBestName -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence -import javax.inject.Inject - -class VerificationEmojiCodeController @Inject constructor( - private val stringProvider: StringProvider, - private val colorProvider: ColorProvider, - private val errorFormatter: ErrorFormatter -) : EpoxyController() { - - var listener: Listener? = null - - private var viewState: VerificationEmojiCodeViewState? = null - - fun update(viewState: VerificationEmojiCodeViewState) { - this.viewState = viewState - requestModelBuild() - } - - override fun buildModels() { - val state = viewState ?: return - - if (state.supportsEmoji) { - buildEmojiItem(state) - } else { - buildDecimal(state) - } - } - - private fun buildEmojiItem(state: VerificationEmojiCodeViewState) { - val host = this - when (val emojiDescription = state.emojiDescription) { - is Success -> { - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.stringProvider.getString(R.string.verification_emoji_notice).toEpoxyCharSequence()) - } - - bottomSheetVerificationEmojisItem { - id("emojis") - emojiRepresentation0(emojiDescription()[0]) - emojiRepresentation1(emojiDescription()[1]) - emojiRepresentation2(emojiDescription()[2]) - emojiRepresentation3(emojiDescription()[3]) - emojiRepresentation4(emojiDescription()[4]) - emojiRepresentation5(emojiDescription()[5]) - emojiRepresentation6(emojiDescription()[6]) - } - - buildActions(state) - } - is Fail -> { - errorWithRetryItem { - id("error") - text(host.errorFormatter.toHumanReadable(emojiDescription.error)) - } - } - else -> { - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.please_wait)) - } - } - } - } - - private fun buildDecimal(state: VerificationEmojiCodeViewState) { - val host = this - when (val decimalDescription = state.decimalDescription) { - is Success -> { - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.stringProvider.getString(R.string.verification_code_notice).toEpoxyCharSequence()) - } - - bottomSheetVerificationDecimalCodeItem { - id("decimal") - code(state.decimalDescription.invoke() ?: "") - } - - buildActions(state) - } - is Fail -> { - errorWithRetryItem { - id("error") - text(host.errorFormatter.toHumanReadable(decimalDescription.error)) - } - } - else -> { - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.please_wait)) - } - } - } - } - - private fun buildActions(state: VerificationEmojiCodeViewState) { - val host = this - bottomSheetDividerItem { - id("sep0") - } - - if (state.isWaitingFromOther) { - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUser.getBestName())) - } - } else { - bottomSheetVerificationActionItem { - id("ko") - title(host.stringProvider.getString(R.string.verification_sas_do_not_match)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - iconRes(R.drawable.ic_check_off) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - listener { host.listener?.onDoNotMatchButtonTapped() } - } - bottomSheetDividerItem { - id("sep1") - } - bottomSheetVerificationActionItem { - id("ok") - title(host.stringProvider.getString(R.string.verification_sas_match)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - iconRes(R.drawable.ic_check_on) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - listener { host.listener?.onMatchButtonTapped() } - } - } - } - - interface Listener { - fun onDoNotMatchButtonTapped() - fun onMatchButtonTapped() - } -} +// /* +// * Copyright 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.emoji +// +// import com.airbnb.epoxy.EpoxyController +// import com.airbnb.mvrx.Fail +// import com.airbnb.mvrx.Success +// import im.vector.app.R +// import im.vector.app.core.epoxy.bottomSheetDividerItem +// import im.vector.app.core.epoxy.errorWithRetryItem +// import im.vector.app.core.error.ErrorFormatter +// import im.vector.app.core.resources.ColorProvider +// import im.vector.app.core.resources.StringProvider +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationDecimalCodeItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationEmojisItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem +// import im.vector.app.features.displayname.getBestName +// import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +// import javax.inject.Inject +// +// class VerificationEmojiCodeController @Inject constructor( +// private val stringProvider: StringProvider, +// private val colorProvider: ColorProvider, +// private val errorFormatter: ErrorFormatter +// ) : EpoxyController() { +// +// var listener: Listener? = null +// +// private var viewState: VerificationEmojiCodeViewState? = null +// +// fun update(viewState: VerificationEmojiCodeViewState) { +// this.viewState = viewState +// requestModelBuild() +// } +// +// override fun buildModels() { +// val state = viewState ?: return +// +// if (state.supportsEmoji) { +// buildEmojiItem(state) +// } else { +// buildDecimal(state) +// } +// } +// +// private fun buildEmojiItem(state: VerificationEmojiCodeViewState) { +// val host = this +// when (val emojiDescription = state.emojiDescription) { +// is Success -> { +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.stringProvider.getString(R.string.verification_emoji_notice).toEpoxyCharSequence()) +// } +// +// bottomSheetVerificationEmojisItem { +// id("emojis") +// emojiRepresentation0(emojiDescription()[0]) +// emojiRepresentation1(emojiDescription()[1]) +// emojiRepresentation2(emojiDescription()[2]) +// emojiRepresentation3(emojiDescription()[3]) +// emojiRepresentation4(emojiDescription()[4]) +// emojiRepresentation5(emojiDescription()[5]) +// emojiRepresentation6(emojiDescription()[6]) +// } +// +// buildActions(state) +// } +// is Fail -> { +// errorWithRetryItem { +// id("error") +// text(host.errorFormatter.toHumanReadable(emojiDescription.error)) +// } +// } +// else -> { +// bottomSheetVerificationWaitingItem { +// id("waiting") +// title(host.stringProvider.getString(R.string.please_wait)) +// } +// } +// } +// } +// +// private fun buildDecimal(state: VerificationEmojiCodeViewState) { +// val host = this +// when (val decimalDescription = state.decimalDescription) { +// is Success -> { +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.stringProvider.getString(R.string.verification_code_notice).toEpoxyCharSequence()) +// } +// +// bottomSheetVerificationDecimalCodeItem { +// id("decimal") +// code(state.decimalDescription.invoke() ?: "") +// } +// +// buildActions(state) +// } +// is Fail -> { +// errorWithRetryItem { +// id("error") +// text(host.errorFormatter.toHumanReadable(decimalDescription.error)) +// } +// } +// else -> { +// bottomSheetVerificationWaitingItem { +// id("waiting") +// title(host.stringProvider.getString(R.string.please_wait)) +// } +// } +// } +// } +// +// private fun buildActions(state: VerificationEmojiCodeViewState) { +// val host = this +// bottomSheetDividerItem { +// id("sep0") +// } +// +// if (state.isWaitingFromOther) { +// bottomSheetVerificationWaitingItem { +// id("waiting") +// title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUser.getBestName())) +// } +// } else { +// bottomSheetVerificationActionItem { +// id("ko") +// title(host.stringProvider.getString(R.string.verification_sas_do_not_match)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// iconRes(R.drawable.ic_check_off) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// listener { host.listener?.onDoNotMatchButtonTapped() } +// } +// bottomSheetDividerItem { +// id("sep1") +// } +// bottomSheetVerificationActionItem { +// id("ok") +// title(host.stringProvider.getString(R.string.verification_sas_match)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// iconRes(R.drawable.ic_check_on) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// listener { host.listener?.onMatchButtonTapped() } +// } +// } +// } +// +// interface Listener { +// fun onDoNotMatchButtonTapped() +// fun onMatchButtonTapped() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeFragment.kt index 419425cdf4..2d43dd4e90 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeFragment.kt @@ -1,81 +1,81 @@ -/* - * 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.emoji - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.airbnb.mvrx.fragmentViewModel -import com.airbnb.mvrx.parentFragmentViewModel -import com.airbnb.mvrx.withState -import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.core.extensions.cleanup -import im.vector.app.core.extensions.configureWith -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding -import im.vector.app.features.crypto.verification.VerificationAction -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import javax.inject.Inject - -@AndroidEntryPoint -class VerificationEmojiCodeFragment : - VectorBaseFragment(), - VerificationEmojiCodeController.Listener { - - @Inject lateinit var controller: VerificationEmojiCodeController - - private val viewModel by fragmentViewModel(VerificationEmojiCodeViewModel::class) - - private val sharedViewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { - return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - setupRecyclerView() - } - - override fun onDestroyView() { - views.bottomSheetVerificationRecyclerView.cleanup() - controller.listener = null - super.onDestroyView() - } - - private fun setupRecyclerView() { - views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) - controller.listener = this - } - - override fun invalidate() = withState(viewModel) { state -> - controller.update(state) - } - - override fun onMatchButtonTapped() = withState(viewModel) { state -> - val otherUserId = state.otherUser.id - val txId = state.transactionId ?: return@withState - sharedViewModel.handle(VerificationAction.SASMatchAction) - } - - override fun onDoNotMatchButtonTapped() = withState(viewModel) { state -> - val otherUserId = state.otherUser.id - val txId = state.transactionId ?: return@withState - sharedViewModel.handle(VerificationAction.SASDoNotMatchAction) - } -} +// /* +// * 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.emoji +// +// import android.os.Bundle +// import android.view.LayoutInflater +// import android.view.View +// import android.view.ViewGroup +// import com.airbnb.mvrx.fragmentViewModel +// import com.airbnb.mvrx.parentFragmentViewModel +// import com.airbnb.mvrx.withState +// import dagger.hilt.android.AndroidEntryPoint +// import im.vector.app.core.extensions.cleanup +// import im.vector.app.core.extensions.configureWith +// import im.vector.app.core.platform.VectorBaseFragment +// import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding +// import im.vector.app.features.crypto.verification.VerificationAction +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel +// import javax.inject.Inject +// +// @AndroidEntryPoint +// class VerificationEmojiCodeFragment : +// VectorBaseFragment(), +// VerificationEmojiCodeController.Listener { +// +// @Inject lateinit var controller: VerificationEmojiCodeController +// +// private val viewModel by fragmentViewModel(VerificationEmojiCodeViewModel::class) +// +// private val sharedViewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) +// +// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { +// return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// +// setupRecyclerView() +// } +// +// override fun onDestroyView() { +// views.bottomSheetVerificationRecyclerView.cleanup() +// controller.listener = null +// super.onDestroyView() +// } +// +// private fun setupRecyclerView() { +// views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) +// controller.listener = this +// } +// +// override fun invalidate() = withState(viewModel) { state -> +// controller.update(state) +// } +// +// override fun onMatchButtonTapped() = withState(viewModel) { state -> +// val otherUserId = state.otherUser.id +// val txId = state.transactionId ?: return@withState +// sharedViewModel.handle(VerificationAction.SASMatchAction) +// } +// +// override fun onDoNotMatchButtonTapped() = withState(viewModel) { state -> +// val otherUserId = state.otherUser.id +// val txId = state.transactionId ?: return@withState +// sharedViewModel.handle(VerificationAction.SASDoNotMatchAction) +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt index 3273af653f..b513bd0773 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt @@ -1,209 +1,209 @@ -/* - * 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.emoji - -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 com.airbnb.mvrx.ViewModelContext -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import dagger.hilt.EntryPoints -import im.vector.app.core.di.MavericksAssistedViewModelFactory -import im.vector.app.core.di.SingletonEntryPoint -import im.vector.app.core.di.hiltMavericksViewModelFactory -import im.vector.app.core.platform.EmptyAction -import im.vector.app.core.platform.EmptyViewEvents -import im.vector.app.core.platform.VectorViewModel -import im.vector.app.features.crypto.verification.VerificationBottomSheet -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation -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.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.getUserOrDefault -import org.matrix.android.sdk.api.util.MatrixItem -import org.matrix.android.sdk.api.util.toMatrixItem - -data class VerificationEmojiCodeViewState( - val transactionId: String?, - val otherUser: MatrixItem, - val supportsEmoji: Boolean = true, - val emojiDescription: Async> = Uninitialized, - val decimalDescription: Async = Uninitialized, - val isWaitingFromOther: Boolean = false -) : MavericksState - -class VerificationEmojiCodeViewModel @AssistedInject constructor( - @Assisted initialState: VerificationEmojiCodeViewState, - private val session: Session -) : VectorViewModel(initialState), VerificationService.Listener { - - init { - - session.cryptoService().verificationService() - .requestEventFlow() - .onEach { - when (it) { - is VerificationEvent.RequestAdded -> verificationRequestCreated(it.request) - is VerificationEvent.RequestUpdated -> verificationRequestUpdated(it.request) - is VerificationEvent.TransactionAdded -> transactionCreated(it.transaction) - is VerificationEvent.TransactionUpdated -> transactionUpdated(it.transaction) - } - } - .launchIn(viewModelScope) - - viewModelScope.launch { - refreshStateFromTx( - session.cryptoService().verificationService() - .getExistingTransaction( - otherUserId = initialState.otherUser.id, - tid = initialState.transactionId ?: "" - ) as? SasVerificationTransaction - ) - - } - -// session.cryptoService().verificationService().addListener(this) - } - -// override fun onCleared() { -// session.cryptoService().verificationService().removeListener(this) -// super.onCleared() +// /* +// * 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.emoji +// +// 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 com.airbnb.mvrx.ViewModelContext +// import dagger.assisted.Assisted +// import dagger.assisted.AssistedFactory +// import dagger.assisted.AssistedInject +// import dagger.hilt.EntryPoints +// import im.vector.app.core.di.MavericksAssistedViewModelFactory +// import im.vector.app.core.di.SingletonEntryPoint +// import im.vector.app.core.di.hiltMavericksViewModelFactory +// import im.vector.app.core.platform.EmptyAction +// import im.vector.app.core.platform.EmptyViewEvents +// import im.vector.app.core.platform.VectorViewModel +// import im.vector.app.features.crypto.verification.VerificationBottomSheet +// import kotlinx.coroutines.flow.launchIn +// import kotlinx.coroutines.flow.onEach +// import kotlinx.coroutines.launch +// import org.matrix.android.sdk.api.session.Session +// import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation +// 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.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.getUserOrDefault +// import org.matrix.android.sdk.api.util.MatrixItem +// import org.matrix.android.sdk.api.util.toMatrixItem +// +// data class VerificationEmojiCodeViewState( +// val transactionId: String?, +// val otherUser: MatrixItem, +// val supportsEmoji: Boolean = true, +// val emojiDescription: Async> = Uninitialized, +// val decimalDescription: Async = Uninitialized, +// val isWaitingFromOther: Boolean = false +// ) : MavericksState +// +// class VerificationEmojiCodeViewModel @AssistedInject constructor( +// @Assisted initialState: VerificationEmojiCodeViewState, +// private val session: Session +// ) : VectorViewModel(initialState), VerificationService.Listener { +// +// init { +// +// session.cryptoService().verificationService() +// .requestEventFlow() +// .onEach { +// when (it) { +// is VerificationEvent.RequestAdded -> verificationRequestCreated(it.request) +// is VerificationEvent.RequestUpdated -> verificationRequestUpdated(it.request) +// is VerificationEvent.TransactionAdded -> transactionCreated(it.transaction) +// is VerificationEvent.TransactionUpdated -> transactionUpdated(it.transaction) +// } +// } +// .launchIn(viewModelScope) +// +// viewModelScope.launch { +// refreshStateFromTx( +// session.cryptoService().verificationService() +// .getExistingTransaction( +// otherUserId = initialState.otherUser.id, +// tid = initialState.transactionId ?: "" +// ) as? SasVerificationTransaction +// ) +// +// } +// +// // session.cryptoService().verificationService().addListener(this) // } - - private fun refreshStateFromTx(sasTx: SasVerificationTransaction?) { - when (val state = sasTx?.state) { - is VerificationTxState.None, - is VerificationTxState.SasStarted, - is VerificationTxState.SasAccepted, - is VerificationTxState.SasKeySent -> { - setState { - copy( - isWaitingFromOther = false, - supportsEmoji = sasTx.supportsEmoji(), - emojiDescription = Loading>() - .takeIf { sasTx.supportsEmoji() } - ?: Uninitialized, - decimalDescription = Loading() - .takeIf { sasTx.supportsEmoji().not() } - ?: Uninitialized - ) - } - } - is VerificationTxState.SasShortCodeReady -> { - setState { - copy( - isWaitingFromOther = false, - supportsEmoji = sasTx.supportsEmoji(), - emojiDescription = if (sasTx.supportsEmoji()) Success(sasTx.getEmojiCodeRepresentation()) - else Uninitialized, - decimalDescription = if (!sasTx.supportsEmoji()) Success(sasTx.getDecimalCodeRepresentation().orEmpty()) - else Uninitialized - ) - } - } - is VerificationTxState.SasMacReceived -> { - if (state.codeConfirmed) { - setState { - copy(isWaitingFromOther = true) - } - } else { - setState { - copy( - isWaitingFromOther = false, - supportsEmoji = sasTx.supportsEmoji(), - emojiDescription = if (sasTx.supportsEmoji()) Success(sasTx.getEmojiCodeRepresentation()) - else Uninitialized, - decimalDescription = if (!sasTx.supportsEmoji()) Success(sasTx.getDecimalCodeRepresentation().orEmpty()) - else Uninitialized - ) - } - } - } - is VerificationTxState.SasMacSent, - is VerificationTxState.Verified -> { - setState { - copy(isWaitingFromOther = true) - } - } - is VerificationTxState.Cancelled -> { - // The fragment should not be rendered in this state, - // it should have been replaced by a conclusion fragment - setState { - copy( - isWaitingFromOther = false, - supportsEmoji = sasTx.supportsEmoji(), - emojiDescription = Fail(Throwable("Transaction Cancelled")), - decimalDescription = Fail(Throwable("Transaction Cancelled")) - ) - } - } - null -> { - setState { - copy( - isWaitingFromOther = false, - emojiDescription = Fail(Throwable("Unknown Transaction")), - decimalDescription = Fail(Throwable("Unknown Transaction")) - ) - } - } - else -> Unit - } - } - - override fun transactionCreated(tx: VerificationTransaction) { - transactionUpdated(tx) - } - - override fun transactionUpdated(tx: VerificationTransaction) = withState { state -> - if (tx.transactionId == state.transactionId && tx is SasVerificationTransaction) { - refreshStateFromTx(tx) - } - } - - @AssistedFactory - interface Factory : MavericksAssistedViewModelFactory { - override fun create(initialState: VerificationEmojiCodeViewState): VerificationEmojiCodeViewModel - } - - companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() { - - override fun initialState(viewModelContext: ViewModelContext): VerificationEmojiCodeViewState { - val args = viewModelContext.args() - val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession() - val matrixItem = session.getUserOrDefault(args.otherUserId).toMatrixItem() - - return VerificationEmojiCodeViewState( - transactionId = args.verificationId, - otherUser = matrixItem - ) - } - } - - override fun handle(action: EmptyAction) { - } -} +// +// // override fun onCleared() { +// // session.cryptoService().verificationService().removeListener(this) +// // super.onCleared() +// // } +// +// private fun refreshStateFromTx(sasTx: SasVerificationTransaction?) { +// when (val state = sasTx?.state) { +// is VerificationTxState.None, +// is VerificationTxState.SasStarted, +// is VerificationTxState.SasAccepted, +// is VerificationTxState.SasKeySent -> { +// setState { +// copy( +// isWaitingFromOther = false, +// supportsEmoji = sasTx.supportsEmoji(), +// emojiDescription = Loading>() +// .takeIf { sasTx.supportsEmoji() } +// ?: Uninitialized, +// decimalDescription = Loading() +// .takeIf { sasTx.supportsEmoji().not() } +// ?: Uninitialized +// ) +// } +// } +// is VerificationTxState.SasShortCodeReady -> { +// setState { +// copy( +// isWaitingFromOther = false, +// supportsEmoji = sasTx.supportsEmoji(), +// emojiDescription = if (sasTx.supportsEmoji()) Success(sasTx.getEmojiCodeRepresentation()) +// else Uninitialized, +// decimalDescription = if (!sasTx.supportsEmoji()) Success(sasTx.getDecimalCodeRepresentation().orEmpty()) +// else Uninitialized +// ) +// } +// } +// is VerificationTxState.SasMacReceived -> { +// if (state.codeConfirmed) { +// setState { +// copy(isWaitingFromOther = true) +// } +// } else { +// setState { +// copy( +// isWaitingFromOther = false, +// supportsEmoji = sasTx.supportsEmoji(), +// emojiDescription = if (sasTx.supportsEmoji()) Success(sasTx.getEmojiCodeRepresentation()) +// else Uninitialized, +// decimalDescription = if (!sasTx.supportsEmoji()) Success(sasTx.getDecimalCodeRepresentation().orEmpty()) +// else Uninitialized +// ) +// } +// } +// } +// is VerificationTxState.SasMacSent, +// is VerificationTxState.Verified -> { +// setState { +// copy(isWaitingFromOther = true) +// } +// } +// is VerificationTxState.Cancelled -> { +// // The fragment should not be rendered in this state, +// // it should have been replaced by a conclusion fragment +// setState { +// copy( +// isWaitingFromOther = false, +// supportsEmoji = sasTx.supportsEmoji(), +// emojiDescription = Fail(Throwable("Transaction Cancelled")), +// decimalDescription = Fail(Throwable("Transaction Cancelled")) +// ) +// } +// } +// null -> { +// setState { +// copy( +// isWaitingFromOther = false, +// emojiDescription = Fail(Throwable("Unknown Transaction")), +// decimalDescription = Fail(Throwable("Unknown Transaction")) +// ) +// } +// } +// else -> Unit +// } +// } +// +// override fun transactionCreated(tx: VerificationTransaction) { +// transactionUpdated(tx) +// } +// +// override fun transactionUpdated(tx: VerificationTransaction) = withState { state -> +// if (tx.transactionId == state.transactionId && tx is SasVerificationTransaction) { +// refreshStateFromTx(tx) +// } +// } +// +// @AssistedFactory +// interface Factory : MavericksAssistedViewModelFactory { +// override fun create(initialState: VerificationEmojiCodeViewState): VerificationEmojiCodeViewModel +// } +// +// companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() { +// +// override fun initialState(viewModelContext: ViewModelContext): VerificationEmojiCodeViewState { +// val args = viewModelContext.args() +// val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession() +// val matrixItem = session.getUserOrDefault(args.otherUserId).toMatrixItem() +// +// return VerificationEmojiCodeViewState( +// transactionId = args.verificationId, +// otherUser = matrixItem +// ) +// } +// } +// +// override fun handle(action: EmptyAction) { +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt index 639ebac29e..0390e0bc2f 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt @@ -1,99 +1,99 @@ -/* - * Copyright 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.qrconfirmation - -import com.airbnb.epoxy.EpoxyController -import im.vector.app.R -import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem -import im.vector.app.features.displayname.getBestName -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence -import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel -import javax.inject.Inject - -class VerificationQrScannedByOtherController @Inject constructor( - private val stringProvider: StringProvider, - private val colorProvider: ColorProvider -) : EpoxyController() { - - var listener: Listener? = null - - private var viewState: VerificationBottomSheetViewState? = null - - fun update(viewState: VerificationBottomSheetViewState) { - this.viewState = viewState - requestModelBuild() - } - - override fun buildModels() { - val state = viewState ?: return - val host = this - - bottomSheetVerificationNoticeItem { - id("notice") - apply { - if (state.isMe) { - notice(host.stringProvider.getString(R.string.qr_code_scanned_self_verif_notice).toEpoxyCharSequence()) - } else { - val name = state.otherUserMxItem.getBestName() - notice(host.stringProvider.getString(R.string.qr_code_scanned_by_other_notice, name).toEpoxyCharSequence()) - } - } - } - - bottomSheetVerificationBigImageItem { - id("image") - roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Trusted) - } - - bottomSheetDividerItem { - id("sep0") - } - - bottomSheetVerificationActionItem { - id("deny") - title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_no)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - iconRes(R.drawable.ic_check_off) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - listener { host.listener?.onUserDeniesQrCodeScanned() } - } - - bottomSheetDividerItem { - id("sep1") - } - - bottomSheetVerificationActionItem { - id("confirm") - title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_yes)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - iconRes(R.drawable.ic_check_on) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - listener { host.listener?.onUserConfirmsQrCodeScanned() } - } - } - - interface Listener { - fun onUserConfirmsQrCodeScanned() - fun onUserDeniesQrCodeScanned() - } -} +// /* +// * Copyright 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.qrconfirmation +// +// import com.airbnb.epoxy.EpoxyController +// import im.vector.app.R +// import im.vector.app.core.epoxy.bottomSheetDividerItem +// import im.vector.app.core.resources.ColorProvider +// import im.vector.app.core.resources.StringProvider +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +// import im.vector.app.features.displayname.getBestName +// import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +// import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +// import javax.inject.Inject +// +// class VerificationQrScannedByOtherController @Inject constructor( +// private val stringProvider: StringProvider, +// private val colorProvider: ColorProvider +// ) : EpoxyController() { +// +// var listener: Listener? = null +// +// private var viewState: VerificationBottomSheetViewState? = null +// +// fun update(viewState: VerificationBottomSheetViewState) { +// this.viewState = viewState +// requestModelBuild() +// } +// +// override fun buildModels() { +// val state = viewState ?: return +// val host = this +// +// bottomSheetVerificationNoticeItem { +// id("notice") +// apply { +// if (state.isMe) { +// notice(host.stringProvider.getString(R.string.qr_code_scanned_self_verif_notice).toEpoxyCharSequence()) +// } else { +// val name = state.otherUserMxItem.getBestName() +// notice(host.stringProvider.getString(R.string.qr_code_scanned_by_other_notice, name).toEpoxyCharSequence()) +// } +// } +// } +// +// bottomSheetVerificationBigImageItem { +// id("image") +// roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Trusted) +// } +// +// bottomSheetDividerItem { +// id("sep0") +// } +// +// bottomSheetVerificationActionItem { +// id("deny") +// title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_no)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// iconRes(R.drawable.ic_check_off) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// listener { host.listener?.onUserDeniesQrCodeScanned() } +// } +// +// bottomSheetDividerItem { +// id("sep1") +// } +// +// bottomSheetVerificationActionItem { +// id("confirm") +// title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_yes)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// iconRes(R.drawable.ic_check_on) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// listener { host.listener?.onUserConfirmsQrCodeScanned() } +// } +// } +// +// interface Listener { +// fun onUserConfirmsQrCodeScanned() +// fun onUserDeniesQrCodeScanned() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherFragment.kt index 0fdbd03174..5d373afd22 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherFragment.kt @@ -1,73 +1,73 @@ -/* - * 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.qrconfirmation - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.airbnb.mvrx.parentFragmentViewModel -import com.airbnb.mvrx.withState -import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.core.extensions.cleanup -import im.vector.app.core.extensions.configureWith -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding -import im.vector.app.features.crypto.verification.VerificationAction -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import javax.inject.Inject - -@AndroidEntryPoint -class VerificationQrScannedByOtherFragment : - VectorBaseFragment(), - VerificationQrScannedByOtherController.Listener { - - @Inject lateinit var controller: VerificationQrScannedByOtherController - - private val sharedViewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { - return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - setupRecyclerView() - } - - override fun invalidate() = withState(sharedViewModel) { state -> - controller.update(state) - } - - override fun onDestroyView() { - views.bottomSheetVerificationRecyclerView.cleanup() - controller.listener = null - super.onDestroyView() - } - - private fun setupRecyclerView() { - views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) - controller.listener = this - } - - override fun onUserConfirmsQrCodeScanned() { - sharedViewModel.handle(VerificationAction.OtherUserScannedSuccessfully) - } - - override fun onUserDeniesQrCodeScanned() { - sharedViewModel.handle(VerificationAction.OtherUserDidNotScanned) - } -} +// /* +// * 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.qrconfirmation +// +// import android.os.Bundle +// import android.view.LayoutInflater +// import android.view.View +// import android.view.ViewGroup +// import com.airbnb.mvrx.parentFragmentViewModel +// import com.airbnb.mvrx.withState +// import dagger.hilt.android.AndroidEntryPoint +// import im.vector.app.core.extensions.cleanup +// import im.vector.app.core.extensions.configureWith +// import im.vector.app.core.platform.VectorBaseFragment +// import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding +// import im.vector.app.features.crypto.verification.VerificationAction +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel +// import javax.inject.Inject +// +// @AndroidEntryPoint +// class VerificationQrScannedByOtherFragment : +// VectorBaseFragment(), +// VerificationQrScannedByOtherController.Listener { +// +// @Inject lateinit var controller: VerificationQrScannedByOtherController +// +// private val sharedViewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) +// +// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { +// return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// setupRecyclerView() +// } +// +// override fun invalidate() = withState(sharedViewModel) { state -> +// controller.update(state) +// } +// +// override fun onDestroyView() { +// views.bottomSheetVerificationRecyclerView.cleanup() +// controller.listener = null +// super.onDestroyView() +// } +// +// private fun setupRecyclerView() { +// views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) +// controller.listener = this +// } +// +// override fun onUserConfirmsQrCodeScanned() { +// sharedViewModel.handle(VerificationAction.OtherUserScannedSuccessfully) +// } +// +// override fun onUserDeniesQrCodeScanned() { +// sharedViewModel.handle(VerificationAction.OtherUserDidNotScanned) +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt index d1b299ded9..31b5fe6755 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt @@ -1,185 +1,185 @@ -/* - * 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.request - -import androidx.core.text.toSpannable -import com.airbnb.epoxy.EpoxyController -import com.airbnb.mvrx.Fail -import com.airbnb.mvrx.Loading -import com.airbnb.mvrx.Success -import com.airbnb.mvrx.Uninitialized -import im.vector.app.R -import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider -import im.vector.app.core.utils.colorizeMatchingText -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState -import im.vector.app.features.crypto.verification.epoxy.bottomSheetSelfWaitItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem -import im.vector.app.features.displayname.getBestName -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence -import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState -import javax.inject.Inject - -class VerificationRequestController @Inject constructor( - private val stringProvider: StringProvider, - private val colorProvider: ColorProvider -) : EpoxyController() { - - var listener: Listener? = null - - private var viewState: VerificationBottomSheetViewState? = null - - fun update(viewState: VerificationBottomSheetViewState) { - this.viewState = viewState - requestModelBuild() - } - - override fun buildModels() { - val state = viewState ?: return - val host = this - - if (state.selfVerificationMode) { - if (state.hasAnyOtherSession) { - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.stringProvider.getString(R.string.verification_open_other_to_verify).toEpoxyCharSequence()) - } - - bottomSheetSelfWaitItem { - id("waiting") - } - - bottomSheetDividerItem { - id("sep") - } - } - - if (state.quadSContainsSecrets) { - val subtitle = if (state.hasAnyOtherSession) { - stringProvider.getString(R.string.verification_use_passphrase) - } else { - null - } - bottomSheetVerificationActionItem { - id("passphrase") - title(host.stringProvider.getString(R.string.verification_cannot_access_other_session)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - subTitle(subtitle) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.onClickRecoverFromPassphrase() } - } - } - - if (!state.isVerificationRequired) { - bottomSheetDividerItem { - id("sep1") - } - - bottomSheetVerificationActionItem { - id("skip") - title(host.stringProvider.getString(R.string.action_skip)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - listener { host.listener?.onClickSkip() } - } - } - } else { - val styledText = - if (state.isMe) { - stringProvider.getString(R.string.verify_new_session_notice) - } else { - stringProvider.getString(R.string.verification_request_notice, state.otherUserId) - .toSpannable() - .colorizeMatchingText(state.otherUserId, colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)) - } - - bottomSheetVerificationNoticeItem { - id("notice") - notice(styledText.toEpoxyCharSequence()) - } - - bottomSheetDividerItem { - id("sep") - } - - when (val pr = state.pendingRequest) { - is Uninitialized -> { - bottomSheetVerificationActionItem { - id("start") - title(host.stringProvider.getString(R.string.start_verification)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - subTitle(host.stringProvider.getString(R.string.verification_request_start_notice)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.onClickOnVerificationStart() } - } - } - is Loading -> { - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUserMxItem.getBestName())) - } - } - is Success -> { - if (pr.invoke().state != EVerificationState.Ready) { - if (state.isMe) { - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.verification_request_waiting)) - } - } else { - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUserMxItem.getBestName())) - } - } - } - } - is Fail -> Unit - } - } - - if (state.isMe && state.currentDeviceCanCrossSign && !state.selfVerificationMode) { - bottomSheetDividerItem { - id("sep_notMe") - } - - bottomSheetVerificationActionItem { - id("wasnote") - title(host.stringProvider.getString(R.string.verify_new_session_was_not_me)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - listener { host.listener?.onClickOnWasNotMe() } - } - } - } - - interface Listener { - fun onClickOnVerificationStart() - fun onClickOnWasNotMe() - fun onClickRecoverFromPassphrase() - fun onClickDismiss() - fun onClickSkip() - } -} +// /* +// * 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.request +// +// import androidx.core.text.toSpannable +// import com.airbnb.epoxy.EpoxyController +// import com.airbnb.mvrx.Fail +// import com.airbnb.mvrx.Loading +// import com.airbnb.mvrx.Success +// import com.airbnb.mvrx.Uninitialized +// import im.vector.app.R +// import im.vector.app.core.epoxy.bottomSheetDividerItem +// import im.vector.app.core.resources.ColorProvider +// import im.vector.app.core.resources.StringProvider +// import im.vector.app.core.utils.colorizeMatchingText +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetSelfWaitItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem +// import im.vector.app.features.displayname.getBestName +// import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +// import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState +// import javax.inject.Inject +// +// class VerificationRequestController @Inject constructor( +// private val stringProvider: StringProvider, +// private val colorProvider: ColorProvider +// ) : EpoxyController() { +// +// var listener: Listener? = null +// +// private var viewState: VerificationBottomSheetViewState? = null +// +// fun update(viewState: VerificationBottomSheetViewState) { +// this.viewState = viewState +// requestModelBuild() +// } +// +// override fun buildModels() { +// val state = viewState ?: return +// val host = this +// +// if (state.selfVerificationMode) { +// if (state.hasAnyOtherSession) { +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.stringProvider.getString(R.string.verification_open_other_to_verify).toEpoxyCharSequence()) +// } +// +// bottomSheetSelfWaitItem { +// id("waiting") +// } +// +// bottomSheetDividerItem { +// id("sep") +// } +// } +// +// if (state.quadSContainsSecrets) { +// val subtitle = if (state.hasAnyOtherSession) { +// stringProvider.getString(R.string.verification_use_passphrase) +// } else { +// null +// } +// bottomSheetVerificationActionItem { +// id("passphrase") +// title(host.stringProvider.getString(R.string.verification_cannot_access_other_session)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// subTitle(subtitle) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.onClickRecoverFromPassphrase() } +// } +// } +// +// if (!state.isVerificationRequired) { +// bottomSheetDividerItem { +// id("sep1") +// } +// +// bottomSheetVerificationActionItem { +// id("skip") +// title(host.stringProvider.getString(R.string.action_skip)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// listener { host.listener?.onClickSkip() } +// } +// } +// } else { +// val styledText = +// if (state.isMe) { +// stringProvider.getString(R.string.verify_new_session_notice) +// } else { +// stringProvider.getString(R.string.verification_request_notice, state.otherUserId) +// .toSpannable() +// .colorizeMatchingText(state.otherUserId, colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)) +// } +// +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(styledText.toEpoxyCharSequence()) +// } +// +// bottomSheetDividerItem { +// id("sep") +// } +// +// when (val pr = state.pendingRequest) { +// is Uninitialized -> { +// bottomSheetVerificationActionItem { +// id("start") +// title(host.stringProvider.getString(R.string.start_verification)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// subTitle(host.stringProvider.getString(R.string.verification_request_start_notice)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.onClickOnVerificationStart() } +// } +// } +// is Loading -> { +// bottomSheetVerificationWaitingItem { +// id("waiting") +// title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUserMxItem.getBestName())) +// } +// } +// is Success -> { +// if (pr.invoke().state != EVerificationState.Ready) { +// if (state.isMe) { +// bottomSheetVerificationWaitingItem { +// id("waiting") +// title(host.stringProvider.getString(R.string.verification_request_waiting)) +// } +// } else { +// bottomSheetVerificationWaitingItem { +// id("waiting") +// title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUserMxItem.getBestName())) +// } +// } +// } +// } +// is Fail -> Unit +// } +// } +// +// if (state.isMe && state.currentDeviceCanCrossSign && !state.selfVerificationMode) { +// bottomSheetDividerItem { +// id("sep_notMe") +// } +// +// bottomSheetVerificationActionItem { +// id("wasnote") +// title(host.stringProvider.getString(R.string.verify_new_session_was_not_me)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized)) +// iconRes(R.drawable.ic_arrow_right) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) +// listener { host.listener?.onClickOnWasNotMe() } +// } +// } +// } +// +// interface Listener { +// fun onClickOnVerificationStart() +// fun onClickOnWasNotMe() +// fun onClickRecoverFromPassphrase() +// fun onClickDismiss() +// fun onClickSkip() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestFragment.kt index d050e4d84a..2cd60a5f60 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestFragment.kt @@ -1,85 +1,85 @@ -/* - * 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.request - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.airbnb.mvrx.parentFragmentViewModel -import com.airbnb.mvrx.withState -import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.core.extensions.cleanup -import im.vector.app.core.extensions.configureWith -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding -import im.vector.app.features.crypto.verification.VerificationAction -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import javax.inject.Inject - -@AndroidEntryPoint -class VerificationRequestFragment : - VectorBaseFragment(), - VerificationRequestController.Listener { - - @Inject lateinit var controller: VerificationRequestController - - private val viewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { - return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - setupRecyclerView() - } - - override fun onDestroyView() { - views.bottomSheetVerificationRecyclerView.cleanup() - controller.listener = null - super.onDestroyView() - } - - private fun setupRecyclerView() { - views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) - controller.listener = this - } - - override fun invalidate() = withState(viewModel) { state -> - controller.update(state) - } - - override fun onClickOnVerificationStart(): Unit = withState(viewModel) { state -> - viewModel.handle(VerificationAction.RequestVerificationByDM) - } - - override fun onClickRecoverFromPassphrase() { - viewModel.handle(VerificationAction.VerifyFromPassphrase) - } - - override fun onClickDismiss() { - viewModel.handle(VerificationAction.SkipVerification) - } - - override fun onClickSkip() { - viewModel.queryCancel() - } - - override fun onClickOnWasNotMe() { - viewModel.itWasNotMe() - } -} +// /* +// * 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.request +// +// import android.os.Bundle +// import android.view.LayoutInflater +// import android.view.View +// import android.view.ViewGroup +// import com.airbnb.mvrx.parentFragmentViewModel +// import com.airbnb.mvrx.withState +// import dagger.hilt.android.AndroidEntryPoint +// import im.vector.app.core.extensions.cleanup +// import im.vector.app.core.extensions.configureWith +// import im.vector.app.core.platform.VectorBaseFragment +// import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding +// import im.vector.app.features.crypto.verification.VerificationAction +// import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel +// import javax.inject.Inject +// +// @AndroidEntryPoint +// class VerificationRequestFragment : +// VectorBaseFragment(), +// VerificationRequestController.Listener { +// +// @Inject lateinit var controller: VerificationRequestController +// +// private val viewModel by parentFragmentViewModel(VerificationBottomSheetViewModel::class) +// +// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { +// return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// setupRecyclerView() +// } +// +// override fun onDestroyView() { +// views.bottomSheetVerificationRecyclerView.cleanup() +// controller.listener = null +// super.onDestroyView() +// } +// +// private fun setupRecyclerView() { +// views.bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) +// controller.listener = this +// } +// +// override fun invalidate() = withState(viewModel) { state -> +// controller.update(state) +// } +// +// override fun onClickOnVerificationStart(): Unit = withState(viewModel) { state -> +// viewModel.handle(VerificationAction.RequestVerificationByDM) +// } +// +// override fun onClickRecoverFromPassphrase() { +// viewModel.handle(VerificationAction.VerifyFromPassphrase) +// } +// +// override fun onClickDismiss() { +// viewModel.handle(VerificationAction.SkipVerification) +// } +// +// override fun onClickSkip() { +// viewModel.queryCancel() +// } +// +// override fun onClickOnWasNotMe() { +// viewModel.itWasNotMe() +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/transaction/VerificationTransactionController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/transaction/VerificationTransactionController.kt index c9a2fb4739..9120388ad3 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/transaction/VerificationTransactionController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/transaction/VerificationTransactionController.kt @@ -1,178 +1,178 @@ -/* - * Copyright (c) 2022 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.transaction - -import com.airbnb.epoxy.EpoxyController -import com.airbnb.mvrx.Async -import com.airbnb.mvrx.Fail -import com.airbnb.mvrx.Loading -import com.airbnb.mvrx.Success -import com.airbnb.mvrx.Uninitialized -import im.vector.app.R -import im.vector.app.core.epoxy.bottomSheetDividerItem -import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationEmojisItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem -import im.vector.app.features.html.EventHtmlRenderer -import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence -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.EmojiRepresentation -import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState -import javax.inject.Inject - -class VerificationTransactionController @Inject constructor( - private val stringProvider: StringProvider, - private val colorProvider: ColorProvider, - private val eventHtmlRenderer: EventHtmlRenderer, -) : EpoxyController() { - - var aTransaction: Async? = null - - fun update(asyncTransaction: Async) { - this.aTransaction = asyncTransaction - requestModelBuild() - } - - override fun buildModels() { - val host = this - when (aTransaction) { - null, - Uninitialized -> { - // empty - } - is Fail -> { - } - is Loading -> { - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.please_wait)) - } - } - is Success -> { - val tx = aTransaction?.invoke() ?: return - if (tx is SasVerificationTransaction) { - when (val txState = tx.state) { - VerificationTxState.SasShortCodeReady -> { - buildEmojiItem(tx.getEmojiCodeRepresentation()) - } - is VerificationTxState.Cancelled -> { - renderCancel(txState.cancelCode) - } - is VerificationTxState.Done -> { - - } - else -> { - // waiting - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.please_wait)) - } - } - } - } - } - } - } - - private fun renderCancel(cancelCode: CancelCode) { - val host = this - when (cancelCode) { - CancelCode.QrCodeInvalid -> { - // TODO - } - CancelCode.MismatchedUser, - CancelCode.MismatchedSas, - CancelCode.MismatchedCommitment, - CancelCode.MismatchedKeys -> { - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.stringProvider.getString(R.string.verification_conclusion_not_secure).toEpoxyCharSequence()) - } - - bottomSheetVerificationBigImageItem { - id("image") - roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Warning) - } - - bottomSheetVerificationNoticeItem { - id("warning_notice") - notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verification_conclusion_compromised)).toEpoxyCharSequence()) - } - } - else -> { - bottomSheetVerificationNoticeItem { - id("notice_cancelled") - notice(host.stringProvider.getString(R.string.verify_cancelled_notice).toEpoxyCharSequence()) - } - } - } - } - - private fun buildEmojiItem(emoji: List) { - val host = this - bottomSheetVerificationNoticeItem { - id("notice") - notice(host.stringProvider.getString(R.string.verification_emoji_notice).toEpoxyCharSequence()) - } - - bottomSheetVerificationEmojisItem { - id("emojis") - emojiRepresentation0(emoji[0]) - emojiRepresentation1(emoji[1]) - emojiRepresentation2(emoji[2]) - emojiRepresentation3(emoji[3]) - emojiRepresentation4(emoji[4]) - emojiRepresentation5(emoji[5]) - emojiRepresentation6(emoji[6]) - } - - buildSasCodeActions() - } - - private fun buildSasCodeActions() { - val host = this - bottomSheetDividerItem { - id("sep0") - } - bottomSheetVerificationActionItem { - id("ko") - title(host.stringProvider.getString(R.string.verification_sas_do_not_match)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - iconRes(R.drawable.ic_check_off) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) - // listener { host.listener?.onDoNotMatchButtonTapped() } - } - bottomSheetDividerItem { - id("sep1") - } - bottomSheetVerificationActionItem { - id("ok") - title(host.stringProvider.getString(R.string.verification_sas_match)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - iconRes(R.drawable.ic_check_on) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - // listener { host.listener?.onMatchButtonTapped() } - } - } -} +// /* +// * Copyright (c) 2022 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.transaction +// +// import com.airbnb.epoxy.EpoxyController +// import com.airbnb.mvrx.Async +// import com.airbnb.mvrx.Fail +// import com.airbnb.mvrx.Loading +// import com.airbnb.mvrx.Success +// import com.airbnb.mvrx.Uninitialized +// import im.vector.app.R +// import im.vector.app.core.epoxy.bottomSheetDividerItem +// import im.vector.app.core.resources.ColorProvider +// import im.vector.app.core.resources.StringProvider +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationEmojisItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +// import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem +// import im.vector.app.features.html.EventHtmlRenderer +// import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence +// 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.EmojiRepresentation +// import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction +// import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction +// import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState +// import javax.inject.Inject +// +// class VerificationTransactionController @Inject constructor( +// private val stringProvider: StringProvider, +// private val colorProvider: ColorProvider, +// private val eventHtmlRenderer: EventHtmlRenderer, +// ) : EpoxyController() { +// +// var aTransaction: Async? = null +// +// fun update(asyncTransaction: Async) { +// this.aTransaction = asyncTransaction +// requestModelBuild() +// } +// +// override fun buildModels() { +// val host = this +// when (aTransaction) { +// null, +// Uninitialized -> { +// // empty +// } +// is Fail -> { +// } +// is Loading -> { +// bottomSheetVerificationWaitingItem { +// id("waiting") +// title(host.stringProvider.getString(R.string.please_wait)) +// } +// } +// is Success -> { +// val tx = aTransaction?.invoke() ?: return +// if (tx is SasVerificationTransaction) { +// when (val txState = tx.state) { +// VerificationTxState.SasShortCodeReady -> { +// buildEmojiItem(tx.getEmojiCodeRepresentation()) +// } +// is VerificationTxState.Cancelled -> { +// renderCancel(txState.cancelCode) +// } +// is VerificationTxState.Done -> { +// +// } +// else -> { +// // waiting +// bottomSheetVerificationWaitingItem { +// id("waiting") +// title(host.stringProvider.getString(R.string.please_wait)) +// } +// } +// } +// } +// } +// } +// } +// +// private fun renderCancel(cancelCode: CancelCode) { +// val host = this +// when (cancelCode) { +// CancelCode.QrCodeInvalid -> { +// // TODO +// } +// CancelCode.MismatchedUser, +// CancelCode.MismatchedSas, +// CancelCode.MismatchedCommitment, +// CancelCode.MismatchedKeys -> { +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.stringProvider.getString(R.string.verification_conclusion_not_secure).toEpoxyCharSequence()) +// } +// +// bottomSheetVerificationBigImageItem { +// id("image") +// roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Warning) +// } +// +// bottomSheetVerificationNoticeItem { +// id("warning_notice") +// notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verification_conclusion_compromised)).toEpoxyCharSequence()) +// } +// } +// else -> { +// bottomSheetVerificationNoticeItem { +// id("notice_cancelled") +// notice(host.stringProvider.getString(R.string.verify_cancelled_notice).toEpoxyCharSequence()) +// } +// } +// } +// } +// +// private fun buildEmojiItem(emoji: List) { +// val host = this +// bottomSheetVerificationNoticeItem { +// id("notice") +// notice(host.stringProvider.getString(R.string.verification_emoji_notice).toEpoxyCharSequence()) +// } +// +// bottomSheetVerificationEmojisItem { +// id("emojis") +// emojiRepresentation0(emoji[0]) +// emojiRepresentation1(emoji[1]) +// emojiRepresentation2(emoji[2]) +// emojiRepresentation3(emoji[3]) +// emojiRepresentation4(emoji[4]) +// emojiRepresentation5(emoji[5]) +// emojiRepresentation6(emoji[6]) +// } +// +// buildSasCodeActions() +// } +// +// private fun buildSasCodeActions() { +// val host = this +// bottomSheetDividerItem { +// id("sep0") +// } +// bottomSheetVerificationActionItem { +// id("ko") +// title(host.stringProvider.getString(R.string.verification_sas_do_not_match)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// iconRes(R.drawable.ic_check_off) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) +// // listener { host.listener?.onDoNotMatchButtonTapped() } +// } +// bottomSheetDividerItem { +// id("sep1") +// } +// bottomSheetVerificationActionItem { +// id("ok") +// title(host.stringProvider.getString(R.string.verification_sas_match)) +// titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// iconRes(R.drawable.ic_check_on) +// iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) +// // listener { host.listener?.onMatchButtonTapped() } +// } +// } +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/transaction/VerificationTransactionFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/transaction/VerificationTransactionFragment.kt index 9f28d416cf..abb752373f 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/transaction/VerificationTransactionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/transaction/VerificationTransactionFragment.kt @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2022 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.transaction - -import android.view.LayoutInflater -import android.view.ViewGroup -import com.airbnb.mvrx.parentFragmentViewModel -import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding -import im.vector.app.features.crypto.verification.user.UserVerificationViewModel - -@AndroidEntryPoint -class VerificationTransactionFragment : VectorBaseFragment() { - - private val viewModel by parentFragmentViewModel(UserVerificationViewModel::class) - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { - return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) - } - -} +// /* +// * Copyright (c) 2022 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.transaction +// +// import android.view.LayoutInflater +// import android.view.ViewGroup +// import com.airbnb.mvrx.parentFragmentViewModel +// import dagger.hilt.android.AndroidEntryPoint +// import im.vector.app.core.platform.VectorBaseFragment +// import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding +// import im.vector.app.features.crypto.verification.user.UserVerificationViewModel +// +// @AndroidEntryPoint +// class VerificationTransactionFragment : VectorBaseFragment() { +// +// private val viewModel by parentFragmentViewModel(UserVerificationViewModel::class) +// +// override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetVerificationChildFragmentBinding { +// return BottomSheetVerificationChildFragmentBinding.inflate(inflater, container, false) +// } +// +// } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationBottomSheet.kt index 9c0749c1ff..9f19d9587c 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationBottomSheet.kt @@ -22,10 +22,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import com.airbnb.mvrx.Fail -import com.airbnb.mvrx.Loading -import com.airbnb.mvrx.Success -import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint @@ -34,15 +30,11 @@ import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetVerificationBinding -import im.vector.app.features.crypto.verification.VerificationBottomSheet import im.vector.app.features.crypto.verification.VerificationBottomSheetViewEvents -import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel -import im.vector.app.features.crypto.verification.cancel.VerificationCancelFragment import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel -import org.matrix.android.sdk.api.session.crypto.verification.EVerificationState import javax.inject.Inject import kotlin.reflect.KClass diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationController.kt index 3e4f6592ab..8561fc2da2 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationController.kt @@ -18,7 +18,6 @@ package im.vector.app.features.crypto.verification.user import androidx.core.text.toSpannable import com.airbnb.epoxy.EpoxyController -import com.airbnb.mvrx.Async import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success @@ -43,8 +42,9 @@ 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.EmojiRepresentation import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest -import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState +import org.matrix.android.sdk.api.session.crypto.verification.QRCodeVerificationState +import org.matrix.android.sdk.api.session.crypto.verification.SasTransactionState +import org.matrix.android.sdk.api.util.MatrixItem import timber.log.Timber import javax.inject.Inject @@ -63,6 +63,8 @@ class UserVerificationController @Inject constructor( fun onMatchButtonTapped() fun openCamera() fun doVerifyBySas() + fun onUserDeniesQrCodeScanned() + fun onUserConfirmsQrCodeScanned() } var listener: InteractionListener? = null @@ -169,7 +171,7 @@ class UserVerificationController @Inject constructor( } } is Fail -> { - //TODO + // TODO } } } @@ -257,28 +259,100 @@ class UserVerificationController @Inject constructor( } private fun renderTransaction(state: UserVerificationViewState, transaction: VerificationTransactionData) { + when (transaction) { + is VerificationTransactionData.QrTransactionData -> { + renderQrTransaction(transaction, state.otherUserMxItem) + } + is VerificationTransactionData.SasTransactionData -> { + renderSasTransaction(transaction) + } + } + } + + private fun renderQrTransaction(transaction: VerificationTransactionData.QrTransactionData, otherUserItem: MatrixItem) { val host = this - if (transaction.method == VerificationMethod.SAS) { - when (val txState = transaction.state) { - VerificationTxState.SasShortCodeReady -> { - buildEmojiItem(transaction.emojiCodeRepresentation.orEmpty()) - } - is VerificationTxState.SasMacReceived -> { - if(!txState.codeConfirmed) { - buildEmojiItem(transaction.emojiCodeRepresentation.orEmpty()) - } else { - // waiting - bottomSheetVerificationWaitingItem { - id("waiting") - title(host.stringProvider.getString(R.string.please_wait)) - } + when (val txState = transaction.state) { + QRCodeVerificationState.Reciprocated -> { + // we are waiting for confirmation from the other side + bottomSheetVerificationNoticeItem { + id("notice") + apply { + notice(host.stringProvider.getString(R.string.qr_code_scanned_verif_waiting_notice).toEpoxyCharSequence()) } } - is VerificationTxState.Cancelled, - is VerificationTxState.Done -> { - // should show request status + + bottomSheetVerificationBigImageItem { + id("image") + roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Trusted) } - else -> { + + bottomSheetVerificationWaitingItem { + id("waiting") + title(host.stringProvider.getString(R.string.qr_code_scanned_verif_waiting, otherUserItem.getBestName())) + } + } + QRCodeVerificationState.WaitingForScanConfirmation -> { + // we need to confirm that the other party actual scanned us + bottomSheetVerificationNoticeItem { + id("notice") + apply { + val name = otherUserItem.getBestName() + notice(host.stringProvider.getString(R.string.qr_code_scanned_by_other_notice, name).toEpoxyCharSequence()) + } + } + + bottomSheetVerificationBigImageItem { + id("image") + roomEncryptionTrustLevel(RoomEncryptionTrustLevel.Trusted) + } + + bottomSheetDividerItem { + id("sep0") + } + + bottomSheetVerificationActionItem { + id("deny") + title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_no)) + titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + iconRes(R.drawable.ic_check_off) + iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError)) + listener { host.listener?.onUserDeniesQrCodeScanned() } + } + + bottomSheetDividerItem { + id("sep1") + } + + bottomSheetVerificationActionItem { + id("confirm") + title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_yes)) + titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + iconRes(R.drawable.ic_check_on) + iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) + listener { host.listener?.onUserConfirmsQrCodeScanned() } + } + } + QRCodeVerificationState.WaitingForOtherDone, + QRCodeVerificationState.Done -> { + // Done + } + QRCodeVerificationState.Cancelled -> { + // Done +// renderCancel(transaction.) + } + } + } + + private fun renderSasTransaction(transaction: VerificationTransactionData.SasTransactionData) { + val host = this + when (val txState = transaction.state) { + SasTransactionState.SasShortCodeReady -> { + buildEmojiItem(transaction.emojiCodeRepresentation.orEmpty()) + } + is SasTransactionState.SasMacReceived -> { + if (!txState.codeConfirmed) { + buildEmojiItem(transaction.emojiCodeRepresentation.orEmpty()) + } else { // waiting bottomSheetVerificationWaitingItem { id("waiting") @@ -286,8 +360,17 @@ class UserVerificationController @Inject constructor( } } } - } else { - // TODO (QR CODe + is SasTransactionState.Cancelled, + is SasTransactionState.Done -> { + // should show request status + } + else -> { + // waiting + bottomSheetVerificationWaitingItem { + id("waiting") + title(host.stringProvider.getString(R.string.please_wait)) + } + } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationFragment.kt index b4c5dbacd6..4cfce1e1dd 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationFragment.kt @@ -140,4 +140,12 @@ class UserVerificationFragment : VectorBaseFragment? -) -fun VerificationTransaction.toDataClass() : VerificationTransactionData { - return VerificationTransactionData( - transactionId = this.transactionId, - state = this.state, - method = this.method, - otherUserId = this.otherUserId, - otherDeviceId = this.otherUserId, - isIncoming = this.isIncoming, - emojiCodeRepresentation = (this as? SasVerificationTransaction)?.getEmojiCodeRepresentation() - ) +sealed class VerificationTransactionData( + open val transactionId: String, + open val otherUserId: String, +) { + + data class SasTransactionData( + override val transactionId: String, + val state: SasTransactionState, + override val otherUserId: String, + val otherDeviceId: String?, + val isIncoming: Boolean, + val emojiCodeRepresentation: List? + ) : VerificationTransactionData(transactionId, otherUserId) + + data class QrTransactionData( + override val transactionId: String, + val state: QRCodeVerificationState, + override val otherUserId: String, + val otherDeviceId: String?, + val isIncoming: Boolean, + ) : VerificationTransactionData(transactionId, otherUserId) +} + +private fun VerificationTransaction.toDataClass(): VerificationTransactionData? { + return when (this) { + is SasVerificationTransaction -> { + VerificationTransactionData.SasTransactionData( + transactionId = this.transactionId, + state = this.state(), + otherUserId = this.otherUserId, + otherDeviceId = this.otherDeviceId, + isIncoming = this.isIncoming, + emojiCodeRepresentation = this.getEmojiCodeRepresentation() + ) + } + is QrCodeVerificationTransaction -> { + VerificationTransactionData.QrTransactionData( + transactionId = this.transactionId, + state = this.state(), + otherUserId = this.otherUserId, + otherDeviceId = this.otherDeviceId, + isIncoming = this.isIncoming, + ) + } + else -> null + } } class UserVerificationViewModel @AssistedInject constructor( @@ -127,8 +152,8 @@ class UserVerificationViewModel @AssistedInject constructor( session.cryptoService().verificationService() .requestEventFlow() .filter { - it.transactionId == currentTransactionId - || currentTransactionId == null && initialState.otherUserId == it.getRequest()?.otherUserId + it.transactionId == currentTransactionId || + currentTransactionId == null && initialState.otherUserId == it.getRequest()?.otherUserId } .onEach { Timber.w("VALR update event ${it.getRequest()} ") @@ -142,10 +167,19 @@ class UserVerificationViewModel @AssistedInject constructor( } it.getTransaction()?.let { Timber.w("VALR state updated transaction to $it") - setState { - copy( - startedTransaction = Success(it.toDataClass()), - ) + val dClass = it.toDataClass() + if (dClass != null) { + setState { + copy( + startedTransaction = Success(dClass), + ) + } + } else { + setState { + copy( + startedTransaction = Fail(IllegalArgumentException("Unsupported Transaction")), + ) + } } } } @@ -229,8 +263,30 @@ class UserVerificationViewModel @AssistedInject constructor( is VerificationAction.GotResultFromSsss -> { // not applicable, only for self verification } - VerificationAction.OtherUserDidNotScanned -> TODO() - VerificationAction.OtherUserScannedSuccessfully -> TODO() + VerificationAction.OtherUserDidNotScanned -> { + withState { state -> + state.startedTransaction.invoke()?.let { + viewModelScope.launch { + val tx = session.cryptoService().verificationService() + .getExistingTransaction(it.otherUserId, it.transactionId) + as? QrCodeVerificationTransaction + tx?.otherUserDidNotScannedMyQrCode() + } + } + } + } + VerificationAction.OtherUserScannedSuccessfully -> { + withState { state -> + state.startedTransaction.invoke()?.let { + viewModelScope.launch { + val tx = session.cryptoService().verificationService() + .getExistingTransaction(it.otherUserId, it.transactionId) + as? QrCodeVerificationTransaction + tx?.otherUserScannedMyQrCode() + } + } + } + } VerificationAction.ReadyPendingVerification -> { withState { state -> state.pendingRequest.invoke()?.let { @@ -244,13 +300,34 @@ class UserVerificationViewModel @AssistedInject constructor( } } } - is VerificationAction.RemoteQrCodeScanned -> TODO() + is VerificationAction.RemoteQrCodeScanned -> { + setState { + copy(startedTransaction = Loading()) + } + withState { state -> + val request = state.pendingRequest.invoke() ?: return@withState + viewModelScope.launch { + try { + session.cryptoService().verificationService() + .reciprocateQRVerification( + request.otherUserId, + request.transactionId, + action.scannedData + ) + } catch (failure: Throwable) { + Timber.w(failure, "Failed to reciprocated") + setState { + copy(startedTransaction = Fail(failure)) + } + } + } + } + } is VerificationAction.RequestVerificationByDM -> { setState { copy(pendingRequest = Loading()) } viewModelScope.launch { - // TODO if self verif we should do via DM val roomId = session.roomService().getExistingDirectRoomWithUser(initialState.otherUserId) ?: session.roomService().createDirectRoom(initialState.otherUserId) @@ -266,14 +343,12 @@ class UserVerificationViewModel @AssistedInject constructor( Timber.w("VALR started request is $request") - setState { copy( pendingRequest = Success(request), transactionId = request.transactionId ) } - } } is VerificationAction.SASDoNotMatchAction -> { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index f82321c03e..ed274a31d3 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -265,7 +265,7 @@ class HomeActivity : HomeActivityViewEvents.PromptToEnableSessionPush -> handlePromptToEnablePush() HomeActivityViewEvents.StartRecoverySetupFlow -> handleStartRecoverySetup() is HomeActivityViewEvents.ForceVerification -> { - //TODO + // TODO // if (it.sendRequest) { navigator.requestSelfSessionVerification(this) // } else { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index cd2f51df5d..473e618e00 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -124,7 +124,6 @@ import im.vector.app.features.call.conference.ConferenceEventObserver import im.vector.app.features.call.conference.JitsiCallViewModel import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.crypto.keysbackup.restore.KeysBackupRestoreActivity -import im.vector.app.features.crypto.verification.VerificationBottomSheet import im.vector.app.features.crypto.verification.user.UserVerificationBottomSheet import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.arguments.TimelineArgs diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index d9fc50260a..5280f0feea 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -52,7 +52,6 @@ import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity import im.vector.app.features.crypto.recover.BootstrapBottomSheet import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.crypto.verification.SupportedVerificationMethodsProvider -import im.vector.app.features.crypto.verification.VerificationBottomSheet import im.vector.app.features.devtools.RoomDevToolActivity import im.vector.app.features.home.room.detail.RoomDetailActivity import im.vector.app.features.home.room.detail.arguments.TimelineArgs diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt index 8c63a13517..020512af36 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -50,7 +50,6 @@ import im.vector.app.databinding.DialogShareQrCodeBinding import im.vector.app.databinding.FragmentMatrixProfileBinding import im.vector.app.databinding.ViewStubRoomMemberProfileHeaderBinding import im.vector.app.features.analytics.plan.MobileScreen -import im.vector.app.features.crypto.verification.VerificationBottomSheet import im.vector.app.features.crypto.verification.user.UserVerificationBottomSheet import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt index c97a218b27..2a0ca4850e 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt @@ -31,7 +31,6 @@ import im.vector.app.R import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetWithFragmentsBinding -import im.vector.app.features.crypto.verification.VerificationBottomSheet import kotlinx.parcelize.Parcelize import kotlin.reflect.KClass @@ -50,11 +49,12 @@ class DeviceListBottomSheet : viewModel.observeViewEvents { when (it) { is DeviceListBottomSheetViewEvents.Verify -> { - VerificationBottomSheet.withArgs( -// roomId = null, - otherUserId = it.userId, - transactionId = it.txID - ).show(requireActivity().supportFragmentManager, "REQPOP") + // TODO selfverif +// VerificationBottomSheet.withArgs( +// // roomId = null, +// otherUserId = it.userId, +// transactionId = it.txID +// ).show(requireActivity().supportFragmentManager, "REQPOP") } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 4a27f63ce0..2255eb9cef 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -60,7 +60,6 @@ import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.crypto.verification.VerificationEvent 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.uia.DefaultBaseAuth import org.matrix.android.sdk.flow.flow import timber.log.Timber @@ -126,7 +125,7 @@ class DevicesViewModel @AssistedInject constructor( session.cryptoService().verificationService().requestEventFlow() .onEach { - when(it) { + when (it) { is VerificationEvent.RequestUpdated -> { if (it.request.isFinished) { queryRefreshDevicesList() @@ -241,7 +240,7 @@ class DevicesViewModel @AssistedInject constructor( } override fun transactionUpdated(tx: VerificationTransaction) { - if (tx.state == VerificationTxState.Verified) { + if (tx.isSuccessful()) { queryRefreshDevicesList() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt index 7e7a7945c8..5e2f0b21f2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt @@ -39,7 +39,6 @@ import im.vector.app.databinding.DialogBaseEditTextBinding import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.auth.ReAuthActivity import im.vector.app.features.crypto.recover.SetupMode -import im.vector.app.features.crypto.verification.VerificationBottomSheet import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import javax.inject.Inject @@ -78,11 +77,12 @@ class VectorSettingsDevicesFragment : is DevicesViewEvents.RequestReAuth -> askForReAuthentication(it) is DevicesViewEvents.PromptRenameDevice -> displayDeviceRenameDialog(it.deviceInfo) is DevicesViewEvents.ShowVerifyDevice -> { - VerificationBottomSheet.withArgs( -// roomId = null, - otherUserId = it.userId, - transactionId = it.transactionId ?: "" - ).show(childFragmentManager, "REQPOP") + // TODO selfverif +// VerificationBottomSheet.withArgs( +// // roomId = null, +// otherUserId = it.userId, +// transactionId = it.transactionId ?: "" +// ).show(childFragmentManager, "REQPOP") } is DevicesViewEvents.SelfVerification -> { navigator.requestSelfSessionVerification(requireActivity()) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSessionsListViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSessionsListViewModel.kt index 6b4c2f4212..c4bbe6fb3e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSessionsListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSessionsListViewModel.kt @@ -25,11 +25,9 @@ import im.vector.app.core.utils.PublishDataSource import im.vector.lib.core.utils.flow.throttleFirst import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.crypto.verification.VerificationEvent 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 kotlin.time.Duration.Companion.seconds abstract class VectorSessionsListViewModel( @@ -85,7 +83,7 @@ abstract class VectorSessionsListViewModel Unit // TODO. Next PR is DevicesViewEvent.PromptRenameDevice -> Unit // TODO. Next PR is DevicesViewEvent.ShowVerifyDevice -> { - VerificationBottomSheet.withArgs( -// roomId = null, - otherUserId = it.userId, - transactionId = it.transactionId ?:"" - ).show(childFragmentManager, "REQPOP") + // TODO selfverif +// VerificationBottomSheet.withArgs( +// // roomId = null, +// otherUserId = it.userId, +// transactionId = it.transactionId ?:"" +// ).show(childFragmentManager, "REQPOP") } is DevicesViewEvent.SelfVerification -> { navigator.requestSelfSessionVerification(requireActivity())