Code review

This commit is contained in:
Valere 2020-01-03 17:36:45 +01:00
parent d1233e8470
commit 08ed8d4fa7
31 changed files with 356 additions and 360 deletions

View file

@ -106,7 +106,6 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
implementation("com.google.guava:guava:28.2-jre")
// Network
implementation 'com.squareup.retrofit2:retrofit:2.6.2'

View file

@ -26,3 +26,8 @@ fun Throwable.is401() =
fun Throwable.isTokenError() =
this is Failure.ServerError
&& (error.code == MatrixError.M_UNKNOWN_TOKEN || error.code == MatrixError.M_MISSING_TOKEN)
fun Throwable.shouldBeRetried(): Boolean {
return this is Failure.NetworkConnection
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
}

View file

@ -81,14 +81,15 @@ interface SasVerificationService {
companion object {
private const val TEN_MINTUTES_IN_MILLIS = 10 * 60 * 1000
private const val FIVE_MINTUTES_IN_MILLIS = 5 * 60 * 1000
fun isValidRequest(age: Long?): Boolean {
if (age == null) return false
val now = System.currentTimeMillis()
val tooInThePast = now - (10 * 60 * 1000)
val fiveMinInMs = 5 * 60 * 1000
val tooInTheFuture = System.currentTimeMillis() + fiveMinInMs
return !(age < tooInThePast || age > tooInTheFuture)
val tooInThePast = now - TEN_MINTUTES_IN_MILLIS
val tooInTheFuture = now + FIVE_MINTUTES_IN_MILLIS
return age in tooInThePast..tooInTheFuture
}
}
}

View file

@ -48,5 +48,5 @@ interface SasVerificationTransaction {
*/
fun userHasVerifiedShortCode()
fun shortCodeDoNotMatch()
fun shortCodeDoesNotMatch()
}

View file

@ -50,7 +50,7 @@ internal data class MessageVerificationAcceptContent(
return true
}
override fun toEventContent() = this.toContent()
override fun toEventContent() = toContent()
companion object : VerificationInfoAcceptFactory {

View file

@ -34,7 +34,7 @@ data class MessageVerificationCancelContent(
override val transactionID: String?
get() = relatesTo?.eventId
override fun toEventContent() = this.toContent()
override fun toEventContent() = toContent()
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || code.isNullOrBlank()) {

View file

@ -32,5 +32,5 @@ internal data class MessageVerificationDoneContent(
override fun isValid() = transactionID?.isNotEmpty() == true
override fun toEventContent(): Content? = this.toContent()
override fun toEventContent(): Content? = toContent()
}

View file

@ -44,7 +44,7 @@ internal data class MessageVerificationKeyContent(
return true
}
override fun toEventContent() = this.toContent()
override fun toEventContent() = toContent()
companion object : VerificationInfoKeyFactory {

View file

@ -33,7 +33,7 @@ internal data class MessageVerificationMacContent(
override val transactionID: String?
get() = relatesTo?.eventId
override fun toEventContent() = this.toContent()
override fun toEventContent() = toContent()
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || keys.isNullOrBlank() || mac.isNullOrEmpty()) {

View file

@ -33,7 +33,7 @@ internal data class MessageVerificationReadyContent(
override val transactionID: String?
get() = relatesTo?.eventId
override fun toEventContent() = this.toContent()
override fun toEventContent() = toContent()
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || methods.isNullOrEmpty() || fromDevice.isNullOrEmpty()) {

View file

@ -62,5 +62,5 @@ internal data class MessageVerificationStartContent(
return true
}
override fun toEventContent() = this.toContent()
override fun toEventContent() = toContent()
}

View file

@ -16,7 +16,6 @@
package im.vector.matrix.android.internal.crypto.verification
import android.content.Context
import android.os.Handler
import android.os.Looper
import dagger.Lazy
@ -52,7 +51,6 @@ import kotlin.collections.set
@SessionScope
internal class DefaultSasVerificationService @Inject constructor(
private val context: Context,
private val credentials: Credentials,
private val cryptoStore: IMXCryptoStore,
private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>,
@ -81,7 +79,7 @@ internal class DefaultSasVerificationService @Inject constructor(
fun onToDeviceEvent(event: Event) {
GlobalScope.launch(coroutineDispatchers.crypto) {
when (event.getClearType()) {
EventType.KEY_VERIFICATION_START -> {
EventType.KEY_VERIFICATION_START -> {
onStartRequestReceived(event)
}
EventType.KEY_VERIFICATION_CANCEL -> {
@ -90,13 +88,13 @@ internal class DefaultSasVerificationService @Inject constructor(
EventType.KEY_VERIFICATION_ACCEPT -> {
onAcceptReceived(event)
}
EventType.KEY_VERIFICATION_KEY -> {
EventType.KEY_VERIFICATION_KEY -> {
onKeyReceived(event)
}
EventType.KEY_VERIFICATION_MAC -> {
EventType.KEY_VERIFICATION_MAC -> {
onMacReceived(event)
}
else -> {
else -> {
// ignore
}
}
@ -106,7 +104,7 @@ internal class DefaultSasVerificationService @Inject constructor(
fun onRoomEvent(event: Event) {
GlobalScope.launch(coroutineDispatchers.crypto) {
when (event.getClearType()) {
EventType.KEY_VERIFICATION_START -> {
EventType.KEY_VERIFICATION_START -> {
onRoomStartRequestReceived(event)
}
EventType.KEY_VERIFICATION_CANCEL -> {
@ -116,24 +114,24 @@ internal class DefaultSasVerificationService @Inject constructor(
EventType.KEY_VERIFICATION_ACCEPT -> {
onRoomAcceptReceived(event)
}
EventType.KEY_VERIFICATION_KEY -> {
EventType.KEY_VERIFICATION_KEY -> {
onRoomKeyRequestReceived(event)
}
EventType.KEY_VERIFICATION_MAC -> {
EventType.KEY_VERIFICATION_MAC -> {
onRoomMacReceived(event)
}
EventType.KEY_VERIFICATION_READY -> {
EventType.KEY_VERIFICATION_READY -> {
onRoomReadyReceived(event)
}
EventType.KEY_VERIFICATION_DONE -> {
EventType.KEY_VERIFICATION_DONE -> {
onRoomDoneReceived(event)
}
EventType.MESSAGE -> {
EventType.MESSAGE -> {
if (MessageType.MSGTYPE_VERIFICATION_REQUEST == event.getClearContent().toModel<MessageContent>()?.type) {
onRoomRequestReceived(event)
}
}
else -> {
else -> {
// ignore
}
}
@ -275,7 +273,7 @@ internal class DefaultSasVerificationService @Inject constructor(
if (startReq?.isValid()?.not() == true) {
Timber.e("## received invalid verification request")
if (startReq.transactionID != null) {
sasTransportRoomMessageFactory.createTransport(context, credentials.userId, credentials.deviceId
sasTransportRoomMessageFactory.createTransport(credentials.userId, credentials.deviceId
?: "", event.roomId
?: "", null).cancelTransaction(
startReq.transactionID ?: "",
@ -288,11 +286,11 @@ internal class DefaultSasVerificationService @Inject constructor(
}
handleStart(otherUserId, startReq as VerificationInfoStart) {
it.transport = sasTransportRoomMessageFactory.createTransport(context, credentials.userId, credentials.deviceId
it.transport = sasTransportRoomMessageFactory.createTransport(credentials.userId, credentials.deviceId
?: "", event.roomId
?: "", it)
}?.let {
sasTransportRoomMessageFactory.createTransport(context, credentials.userId, credentials.deviceId
sasTransportRoomMessageFactory.createTransport(credentials.userId, credentials.deviceId
?: "", event.roomId
?: "", null).cancelTransaction(
startReq.transactionID ?: "",
@ -701,7 +699,7 @@ internal class DefaultSasVerificationService @Inject constructor(
pendingRequests[userId] = it
}
val transport = sasTransportRoomMessageFactory.createTransport(context, credentials.userId, credentials.deviceId
val transport = sasTransportRoomMessageFactory.createTransport(credentials.userId, credentials.deviceId
?: "", roomId, null)
// Cancel existing pending requests?
@ -738,7 +736,7 @@ internal class DefaultSasVerificationService @Inject constructor(
}
override fun declineVerificationRequestInDMs(otherUserId: String, otherDeviceId: String, transactionId: String, roomId: String) {
sasTransportRoomMessageFactory.createTransport(context, credentials.userId, credentials.deviceId
sasTransportRoomMessageFactory.createTransport(credentials.userId, credentials.deviceId
?: "", roomId, null).cancelTransaction(transactionId, otherUserId, otherDeviceId, CancelCode.User)
getExistingVerificationRequest(otherUserId, transactionId)?.let {
@ -776,7 +774,7 @@ internal class DefaultSasVerificationService @Inject constructor(
transactionId,
otherUserId,
otherDeviceId)
tx.transport = sasTransportRoomMessageFactory.createTransport(context, credentials.userId, credentials.deviceId
tx.transport = sasTransportRoomMessageFactory.createTransport(credentials.userId, credentials.deviceId
?: "", roomId, tx)
addTransaction(tx)
@ -791,7 +789,7 @@ internal class DefaultSasVerificationService @Inject constructor(
// Let's find the related request
getExistingVerificationRequest(otherUserId)?.find { it.transactionId == transactionId }?.let {
// we need to send a ready event, with matching methods
val transport = sasTransportRoomMessageFactory.createTransport(context, credentials.userId, credentials.deviceId
val transport = sasTransportRoomMessageFactory.createTransport(credentials.userId, credentials.deviceId
?: "", roomId, null)
val methods = it.requestInfo?.methods?.intersect(listOf(KeyVerificationStart.VERIF_METHOD_SAS))?.toList()
if (methods.isNullOrEmpty()) {

View file

@ -169,7 +169,7 @@ internal abstract class SASVerificationTransaction(
} // if not wait for it
}
override fun shortCodeDoNotMatch() {
override fun shortCodeDoesNotMatch() {
Timber.v("## SAS short code do not match for id:$transactionId")
cancel(CancelCode.MismatchedSas)
}

View file

@ -284,10 +284,11 @@ internal class SasTransportRoomMessage(
}
internal class SasTransportRoomMessageFactory @Inject constructor(
private val context: Context,
private val monarchy: Monarchy,
private val localEchoEventFactory: LocalEchoEventFactory) {
fun createTransport(context: Context, userId: String, userDevice: String, roomId: String, tx: SASVerificationTransaction?
fun createTransport(userId: String, userDevice: String, roomId: String, tx: SASVerificationTransaction?
): SasTransportRoomMessage {
return SasTransportRoomMessage(context, userId, userDevice, roomId, monarchy, localEchoEventFactory, tx)
}

View file

@ -1,3 +1,18 @@
/*
* 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.matrix.android.internal.crypto.verification
import android.content.Context
@ -5,8 +20,7 @@ import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass
import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.failure.MatrixError
import im.vector.matrix.android.api.failure.shouldBeRetried
import im.vector.matrix.android.api.session.crypto.CryptoService
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.internal.crypto.tasks.SendVerificationMessageTask
@ -35,10 +49,11 @@ internal class SendVerificationMessageWorker constructor(context: Context, param
val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.success(errorOutputData)
val sessionComponent = getSessionComponent(params.userId) ?: return Result.success(errorOutputData).also {
// TODO, can this happen? should I update local echo?
Timber.e("Unknown Session, cannot send message, userId:${params.userId}")
}
val sessionComponent = getSessionComponent(params.userId)
?: return Result.success(errorOutputData).also {
// TODO, can this happen? should I update local echo?
Timber.e("Unknown Session, cannot send message, userId:${params.userId}")
}
sessionComponent.inject(this)
val localId = params.event.eventId ?: ""
return try {
@ -58,9 +73,4 @@ internal class SendVerificationMessageWorker constructor(context: Context, param
}
}
}
private fun Throwable.shouldBeRetried(): Boolean {
return this is Failure.NetworkConnection
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
}
}

View file

@ -20,8 +20,7 @@ import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass
import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.failure.MatrixError
import im.vector.matrix.android.api.failure.shouldBeRetried
import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.send.SendState
@ -77,11 +76,6 @@ internal class SendEventWorker constructor(context: Context, params: WorkerParam
}
}
private fun Throwable.shouldBeRetried(): Boolean {
return this is Failure.NetworkConnection
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
}
private suspend fun sendEvent(eventId: String, eventType: String, content: Content?, roomId: String) {
localEchoUpdater.updateSendState(eventId, SendState.SENDING)
executeRequest<SendResponse> {

View file

@ -21,21 +21,4 @@
<string name="key_verification_request_fallback_message">%s is requesting to verify your key, but your client does not support in-chat key verification. You will need to use legacy key verification to verify keys.</string>
<!-- Sender name of a message when it is send by you, e.g. You: Hello!-->
<string name="you">You</string>
<string name="verify_by_scanning_title">Verify by scanning</string>
<!-- the %s will be replaced by verify_open_camera_link that will be clickable -->
<string name="verify_by_scanning_description">Ask the other user to scan this code, or %s to scan theirs</string>
<!-- This part is inserted in verify_by_scanning_description-->
<string name="verify_open_camera_link">open your camera</string>
<string name="verify_by_emoji_title">Verify by Emoji</string>
<string name="verify_by_emoji_description">If you cant scan the code above, verify by comparing a short, unique selection of emoji.</string>
<string name="aria_qr_code_description">QR code image</string>
<string name="verification_request_alert_title">Verify %s</string>
<string name="verification_request_waiting_for">Waiting for %s…</string>
<string name="verification_request_alert_description">For extra security, verify %s by checking a one-time code on both your devices.\n\nFor maximum security, do this in person.</string>
</resources>

View file

@ -1,5 +1,5 @@
/*
* Copyright 2018 New Vector Ltd
* 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.

View file

@ -109,13 +109,13 @@ class SASVerificationCodeFragment @Inject constructor(
sasCodeWaitingPartnerText.isVisible = false
}
}
is Fail -> {
is Fail -> {
sasLoadingProgress.isVisible = false
emojiGrid.isInvisible = true
ButtonsVisibilityGroup.isInvisible = true
// TODO?
}
else -> {
else -> {
sasLoadingProgress.isVisible = true
emojiGrid.isInvisible = true
ButtonsVisibilityGroup.isInvisible = true
@ -142,17 +142,21 @@ class SASVerificationCodeFragment @Inject constructor(
@OnClick(R.id.sas_request_continue_button)
fun onMatchButtonTapped() = withState(viewModel) { state ->
val otherUserId = state.otherUser?.id ?: return@withState
val txId = state.transactionId ?: return@withState
// UX echo
ButtonsVisibilityGroup.isInvisible = true
sasCodeWaitingPartnerText.isVisible = true
sharedViewModel.handle(VerificationAction.SASMatchAction(state.otherUserId, state.transactionId))
sharedViewModel.handle(VerificationAction.SASMatchAction(otherUserId, txId))
}
@OnClick(R.id.sas_request_cancel_button)
fun onDoNotMatchButtonTapped() = withState(viewModel) { state ->
val otherUserId = state.otherUser?.id ?: return@withState
val txId = state.transactionId ?: return@withState
// UX echo
ButtonsVisibilityGroup.isInvisible = true
sasCodeWaitingPartnerText.isVisible = true
sharedViewModel.handle(VerificationAction.SASDoNotMatchAction(state.otherUserId, state.transactionId))
sharedViewModel.handle(VerificationAction.SASDoNotMatchAction(otherUserId, txId))
}
}

View file

@ -25,12 +25,12 @@ import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTransactio
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTxState
import im.vector.matrix.android.api.util.MatrixItem
import im.vector.matrix.android.api.util.toMatrixItem
import im.vector.riotx.core.di.HasScreenInjector
import im.vector.riotx.core.platform.EmptyAction
import im.vector.riotx.core.platform.VectorViewModel
data class SASVerificationCodeViewState(
val transactionId: String,
val otherUserId: String,
val transactionId: String?,
val otherUser: MatrixItem? = null,
val supportsEmoji: Boolean = true,
val emojiDescription: Async<List<EmojiRepresentation>> = Uninitialized,
@ -45,23 +45,9 @@ class SASVerificationCodeViewModel @AssistedInject constructor(
init {
withState { state ->
val matrixItem = session.getUser(state.otherUserId)?.toMatrixItem()
setState {
copy(otherUser = matrixItem)
}
val sasTx = session.getSasVerificationService()
.getExistingTransaction(state.otherUserId, state.transactionId)
if (sasTx == null) {
setState {
copy(
isWaitingFromOther = false,
emojiDescription = Fail(Throwable("Unknown Transaction")),
decimalDescription = Fail(Throwable("Unknown Transaction"))
)
}
} else {
refreshStateFromTx(sasTx)
}
refreshStateFromTx(session.getSasVerificationService()
.getExistingTransaction(state.otherUser?.id ?: "", state.transactionId
?: ""))
}
session.getSasVerificationService().addListener(this)
@ -72,8 +58,8 @@ class SASVerificationCodeViewModel @AssistedInject constructor(
super.onCleared()
}
private fun refreshStateFromTx(sasTx: SasVerificationTransaction) {
when (sasTx.state) {
private fun refreshStateFromTx(sasTx: SasVerificationTransaction?) {
when (sasTx?.state) {
SasVerificationTxState.None,
SasVerificationTxState.SendingStart,
SasVerificationTxState.Started,
@ -131,6 +117,15 @@ class SASVerificationCodeViewModel @AssistedInject constructor(
)
}
}
null -> {
setState {
copy(
isWaitingFromOther = false,
emojiDescription = Fail(Throwable("Unknown Transaction")),
decimalDescription = Fail(Throwable("Unknown Transaction"))
)
}
}
}
}
@ -138,8 +133,10 @@ class SASVerificationCodeViewModel @AssistedInject constructor(
transactionUpdated(tx)
}
override fun transactionUpdated(tx: SasVerificationTransaction) {
refreshStateFromTx(tx)
override fun transactionUpdated(tx: SasVerificationTransaction) = withState { state ->
if (tx.transactionId == state.transactionId) {
refreshStateFromTx(tx)
}
}
@AssistedInject.Factory
@ -156,9 +153,12 @@ class SASVerificationCodeViewModel @AssistedInject constructor(
override fun initialState(viewModelContext: ViewModelContext): SASVerificationCodeViewState? {
val args = viewModelContext.args<VerificationBottomSheet.VerificationArgs>()
val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession()
val matrixItem = session.getUser(args.otherUserId)?.toMatrixItem()
return SASVerificationCodeViewState(
transactionId = args.verificationId ?: "",
otherUserId = args.otherUserId
transactionId = args.verificationId,
otherUser = matrixItem
)
}
}

View file

@ -30,6 +30,7 @@ import androidx.transition.AutoTransition
import androidx.transition.TransitionManager
import butterknife.BindView
import butterknife.ButterKnife
import butterknife.Unbinder
import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.fragmentViewModel
@ -75,12 +76,20 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
@BindView(R.id.verificationRequestAvatar)
lateinit var otherUserAvatarImageView: ImageView
private var unBinder: Unbinder? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.bottom_sheet_verification, container, false)
ButterKnife.bind(this, view)
unBinder = ButterKnife.bind(this, view)
return view
}
override fun onDestroyView() {
super.onDestroyView()
unBinder?.unbind()
unBinder = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@ -183,6 +192,20 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
}
}
}
companion object {
fun withArgs(roomId: String, otherUserId: String, transactionId: String? = null): VerificationBottomSheet {
return VerificationBottomSheet().apply {
arguments = Bundle().apply {
putParcelable(MvRx.KEY_ARG, VerificationBottomSheet.VerificationArgs(
otherUserId = otherUserId,
roomId = roomId,
verificationId = transactionId
))
}
}
}
}
}
fun View.getParentCoordinatorLayout(): CoordinatorLayout? {

View file

@ -112,8 +112,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
}
}
is VerificationAction.StartSASVerification -> {
val request = session.getSasVerificationService().getExistingVerificationRequest(otherUserId)
?.firstOrNull { it.transactionId == action.pendingRequestTransactionId }
val request = session.getSasVerificationService().getExistingVerificationRequest(otherUserId, action.pendingRequestTransactionId)
?: return@withState
val otherDevice = if (request.isIncoming) request.requestInfo?.fromDevice else request.readyInfo?.fromDevice
@ -134,7 +133,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
is VerificationAction.SASDoNotMatchAction -> {
session.getSasVerificationService()
.getExistingTransaction(action.userID, action.sasTransactionId)
?.shortCodeDoNotMatch()
?.shortCodeDoesNotMatch()
}
is VerificationAction.GotItConclusion -> {
_requestLiveData.postValue(LiveEvent(Success(action)))

View file

@ -23,6 +23,7 @@ import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart
import im.vector.riotx.core.di.HasScreenInjector
import im.vector.riotx.core.platform.EmptyAction
import im.vector.riotx.core.platform.VectorViewModel
@ -38,19 +39,6 @@ class VerificationChooseMethodViewModel @AssistedInject constructor(
private val session: Session
) : VectorViewModel<VerificationChooseMethodViewState, EmptyAction>(initialState) {
init {
withState { state ->
val pvr = session.getSasVerificationService().getExistingVerificationRequest(state.otherUserId)?.first {
it.transactionId == state.transactionId
}
val qrAvailable = pvr?.readyInfo?.methods?.contains(KeyVerificationStart.VERIF_METHOD_SCAN) ?: false
val emojiAvailable = pvr?.readyInfo?.methods?.contains(KeyVerificationStart.VERIF_METHOD_SAS) ?: false
setState {
copy(QRModeAvailable = qrAvailable, SASMOdeAvailable = emojiAvailable)
}
}
}
@AssistedInject.Factory
interface Factory {
fun create(initialState: VerificationChooseMethodViewState): VerificationChooseMethodViewModel
@ -64,7 +52,18 @@ class VerificationChooseMethodViewModel @AssistedInject constructor(
override fun initialState(viewModelContext: ViewModelContext): VerificationChooseMethodViewState? {
val args: VerificationBottomSheet.VerificationArgs = viewModelContext.args()
return VerificationChooseMethodViewState(otherUserId = args.otherUserId, transactionId = args.verificationId ?: "")
val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession()
val pvr = session.getSasVerificationService().getExistingVerificationRequest(args.otherUserId, args.verificationId)
val qrAvailable = pvr?.readyInfo?.methods?.contains(KeyVerificationStart.VERIF_METHOD_SCAN)
?: false
val emojiAvailable = pvr?.readyInfo?.methods?.contains(KeyVerificationStart.VERIF_METHOD_SAS)
?: false
return VerificationChooseMethodViewState(otherUserId = args.otherUserId,
transactionId = args.verificationId ?: "",
QRModeAvailable = qrAvailable,
SASMOdeAvailable = emojiAvailable
)
}
}

View file

@ -17,6 +17,7 @@ package im.vector.riotx.features.crypto.verification
import android.os.Parcelable
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import butterknife.OnClick
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.parentFragmentViewModel
@ -53,7 +54,7 @@ class VerificationConclusionFragment @Inject constructor() : VectorBaseFragment(
}
ConclusionState.WARNING -> {
verificationConclusionTitle.text = getString(R.string.verification_conclusion_not_secure)
verifyConclusionDescription.setTextOrHide(null)
verifyConclusionDescription.isVisible = false
verifyConclusionImageView.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_shield_warning))
verifyConclusionBottomDescription.text = Markwon.builder(requireContext())

View file

@ -25,6 +25,7 @@ import im.vector.matrix.android.api.util.MatrixItem
import im.vector.matrix.android.api.util.toMatrixItem
import im.vector.matrix.android.internal.crypto.verification.PendingVerificationRequest
import im.vector.riotx.core.di.HasScreenInjector
import im.vector.riotx.core.platform.EmptyAction
import im.vector.riotx.core.platform.VectorViewModel
data class VerificationRequestViewState(
@ -36,7 +37,7 @@ data class VerificationRequestViewState(
class VerificationRequestViewModel @AssistedInject constructor(
@Assisted initialState: VerificationRequestViewState,
private val session: Session
) : VectorViewModel<VerificationRequestViewState, VerificationAction>(initialState), SasVerificationService.SasVerificationListener {
) : VectorViewModel<VerificationRequestViewState, EmptyAction>(initialState), SasVerificationService.SasVerificationListener {
@AssistedInject.Factory
interface Factory {
@ -75,8 +76,7 @@ class VerificationRequestViewModel @AssistedInject constructor(
}
}
override fun handle(action: VerificationAction) {
}
override fun handle(action: EmptyAction) {}
override fun transactionCreated(tx: SasVerificationTransaction) {}

View file

@ -432,7 +432,8 @@ class RoomDetailFragment @Inject constructor(
composerLayout.sendButton.setContentDescription(getString(descriptionRes))
avatarRenderer.render(
MatrixItem.UserItem(event.root.senderId ?: "", event.getDisambiguatedDisplayName(), event.senderAvatar),
MatrixItem.UserItem(event.root.senderId
?: "", event.getDisambiguatedDisplayName(), event.senderAvatar),
composerLayout.composerRelatedMessageAvatar
)
composerLayout.expand {
@ -962,20 +963,17 @@ class RoomDetailFragment @Inject constructor(
}
}
is RoomDetailAction.RequestVerification -> {
VerificationBottomSheet().apply {
arguments = Bundle().apply {
putParcelable(MvRx.KEY_ARG, VerificationBottomSheet.VerificationArgs(data.userId, roomId = roomDetailArgs.roomId))
}
// setArguments()
}.show(parentFragmentManager, "REQ")
VerificationBottomSheet.withArgs(
roomDetailArgs.roomId,
data.userId
).show(parentFragmentManager, "REQ")
}
is RoomDetailAction.AcceptVerificationRequest -> {
VerificationBottomSheet().apply {
arguments = Bundle().apply {
putParcelable(MvRx.KEY_ARG, VerificationBottomSheet.VerificationArgs(
data.otherUserId, data.transactionId, roomId = roomDetailArgs.roomId))
}
}.show(parentFragmentManager, "REQ")
VerificationBottomSheet.withArgs(
roomDetailArgs.roomId,
data.otherUserId,
data.transactionId
).show(parentFragmentManager, "REQ")
}
}
}

View file

@ -73,7 +73,7 @@ abstract class VerificationRequestItem : AbsBaseMessageItem<VerificationRequestI
when (attributes.informationData.referencesInfoData?.verificationStatus) {
VerificationState.REQUEST,
null -> {
null -> {
holder.buttonBar.isVisible = !attributes.informationData.sentByMe
holder.statusTextView.text = null
holder.statusTextView.isVisible = false
@ -83,17 +83,17 @@ abstract class VerificationRequestItem : AbsBaseMessageItem<VerificationRequestI
holder.statusTextView.text = holder.view.context.getString(R.string.verification_request_other_cancelled, attributes.informationData.memberName)
holder.statusTextView.isVisible = true
}
VerificationState.CANCELED_BY_ME -> {
VerificationState.CANCELED_BY_ME -> {
holder.buttonBar.isVisible = false
holder.statusTextView.text = holder.view.context.getString(R.string.verification_request_you_cancelled)
holder.statusTextView.isVisible = true
}
VerificationState.WAITING -> {
VerificationState.WAITING -> {
holder.buttonBar.isVisible = false
holder.statusTextView.text = holder.view.context.getString(R.string.verification_request_waiting)
holder.statusTextView.isVisible = true
}
VerificationState.DONE -> {
VerificationState.DONE -> {
holder.buttonBar.isVisible = false
holder.statusTextView.text = if (attributes.informationData.sentByMe) {
holder.view.context.getString(R.string.verification_request_other_accepted, attributes.otherUserName)
@ -102,7 +102,7 @@ abstract class VerificationRequestItem : AbsBaseMessageItem<VerificationRequestI
}
holder.statusTextView.isVisible = true
}
else -> {
else -> {
holder.buttonBar.isVisible = false
holder.statusTextView.text = null
holder.statusTextView.isVisible = false
@ -110,7 +110,9 @@ abstract class VerificationRequestItem : AbsBaseMessageItem<VerificationRequestI
}
// Always hide buttons if request is too old
holder.buttonBar.isVisible = holder.buttonBar.isVisible && SasVerificationService.isValidRequest(attributes.informationData.ageLocalTS)
if (!SasVerificationService.isValidRequest(attributes.informationData.ageLocalTS)) {
holder.buttonBar.isVisible = false
}
holder.callback = callback
holder.attributes = attributes

View file

@ -1,195 +1,188 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:background="?android:colorBackground">
<TextView
android:id="@+id/sas_emoji_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_horizontal_margin"
android:layout_marginTop="@dimen/layout_vertical_margin"
android:text="@string/verify_by_emoji_title"
android:textColor="?riotx_text_primary"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/sas_emoji_description_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_vertical_margin"
android:text="@string/verify_user_sas_emoji_help_text"
android:textColor="?riotx_text_secondary"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/sas_emoji_description" />
<TextView
android:id="@+id/sas_decimal_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="?riotx_text_primary"
android:textSize="28sp"
android:textStyle="bold"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/sas_emoji_grid"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/sas_emoji_grid"
tools:text="1234-4320-3905"
tools:visibility="visible" />
<ProgressBar
android:id="@+id/sasLoadingProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:layout_constraintBottom_toBottomOf="@+id/sas_emoji_grid"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/sas_emoji_grid" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:id="@+id/sas_emoji_grid"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_vertical_margin"
android:visibility="invisible"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_description_2"
tools:visibility="visible">
<TextView
android:id="@+id/sas_emoji_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_horizontal_margin"
android:layout_marginTop="@dimen/layout_vertical_margin"
android:text="@string/verify_by_emoji_title"
android:textColor="?riotx_text_primary"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include
android:id="@+id/emoji0"
layout="@layout/item_emoji_verif" />
<TextView
android:id="@+id/sas_emoji_description_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_vertical_margin"
android:text="@string/verify_user_sas_emoji_help_text"
android:textColor="?riotx_text_secondary"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/sas_emoji_description" />
<include
android:id="@+id/emoji1"
layout="@layout/item_emoji_verif" />
<TextView
android:id="@+id/sas_decimal_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="?riotx_text_primary"
android:textSize="28sp"
android:textStyle="bold"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/sas_emoji_grid"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/sas_emoji_grid"
tools:text="1234-4320-3905"
tools:visibility="visible" />
<include
android:id="@+id/emoji2"
layout="@layout/item_emoji_verif" />
<ProgressBar
android:id="@+id/sasLoadingProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:layout_constraintBottom_toBottomOf="@+id/sas_emoji_grid"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/sas_emoji_grid"
/>
<include
android:id="@+id/emoji3"
layout="@layout/item_emoji_verif" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/sas_emoji_grid"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_vertical_margin"
android:visibility="invisible"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_description_2"
tools:visibility="visible">
<include
android:id="@+id/emoji4"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji0"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji5"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji1"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji6"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji2"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji3"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji4"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji5"
layout="@layout/item_emoji_verif" />
<include
android:id="@+id/emoji6"
layout="@layout/item_emoji_verif" />
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/sas_emoji_grid_flow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:constraint_referenced_ids="emoji0,emoji1,emoji2,emoji3,emoji4,emoji5,emoji6"
app:flow_horizontalBias="0.5"
app:flow_horizontalGap="16dp"
app:flow_horizontalStyle="packed"
app:flow_verticalBias="0"
app:flow_verticalGap="8dp"
app:flow_wrapMode="chain"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/sas_request_continue_button"
style="@style/VectorButtonStylePositive"
android:layout_width="0dp"
android:layout_margin="@dimen/layout_vertical_margin"
android:minWidth="160dp"
android:text="@string/verification_sas_match"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/centerGuideLine"
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_grid"
tools:text="A very long translation thats too big" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/centerGuideLine"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<com.google.android.material.button.MaterialButton
android:id="@+id/sas_request_cancel_button"
style="@style/VectorButtonStyleDestructive"
android:layout_width="0dp"
android:layout_margin="@dimen/layout_vertical_margin"
android:text="@string/verification_sas_do_not_match"
app:layout_constraintEnd_toStartOf="@+id/centerGuideLine"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_grid" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/bottomBarrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:barrierMargin="8dp"
app:constraint_referenced_ids="sas_request_cancel_button,sas_request_continue_button" />
<TextView
android:id="@+id/sasCodeWaitingPartnerText"
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/sas_emoji_grid_flow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="?attr/vctr_notice_secondary"
android:textSize="15sp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/bottomBarrier"
app:layout_constraintTop_toBottomOf="@id/sas_emoji_grid"
android:text="@string/sas_waiting_for_partner"
tools:visibility="visible" />
<TextView
android:id="@+id/sasEmojiSecurityTip"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_vertical_margin"
android:gravity="center"
android:text="@string/verify_user_sas_emoji_security_tip"
android:textColor="?riotx_text_secondary"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bottomBarrier" />
<androidx.constraintlayout.widget.Group
android:id="@+id/ButtonsVisibilityGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="sas_request_continue_button,sas_request_cancel_button"
tools:visibility="visible" />
app:constraint_referenced_ids="emoji0,emoji1,emoji2,emoji3,emoji4,emoji5,emoji6"
app:flow_horizontalBias="0.5"
app:flow_horizontalGap="16dp"
app:flow_horizontalStyle="packed"
app:flow_verticalBias="0"
app:flow_verticalGap="8dp"
app:flow_wrapMode="chain"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<com.google.android.material.button.MaterialButton
android:id="@+id/sas_request_continue_button"
style="@style/VectorButtonStylePositive"
android:layout_width="0dp"
android:layout_margin="@dimen/layout_vertical_margin"
android:minWidth="160dp"
android:text="@string/verification_sas_match"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/centerGuideLine"
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_grid"
tools:text="A very long translation thats too big" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/centerGuideLine"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<com.google.android.material.button.MaterialButton
android:id="@+id/sas_request_cancel_button"
style="@style/VectorButtonStyleDestructive"
android:layout_width="0dp"
android:layout_margin="@dimen/layout_vertical_margin"
android:text="@string/verification_sas_do_not_match"
app:layout_constraintEnd_toStartOf="@+id/centerGuideLine"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_grid" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/bottomBarrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:barrierMargin="8dp"
app:constraint_referenced_ids="sas_request_cancel_button,sas_request_continue_button" />
<TextView
android:id="@+id/sasCodeWaitingPartnerText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/sas_waiting_for_partner"
android:textColor="?attr/vctr_notice_secondary"
android:textSize="15sp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/bottomBarrier"
app:layout_constraintTop_toBottomOf="@id/sas_emoji_grid"
tools:visibility="visible" />
<TextView
android:id="@+id/sasEmojiSecurityTip"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_vertical_margin"
android:gravity="center"
android:text="@string/verify_user_sas_emoji_security_tip"
android:textColor="?riotx_text_secondary"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bottomBarrier" />
<androidx.constraintlayout.widget.Group
android:id="@+id/ButtonsVisibilityGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="sas_request_continue_button,sas_request_cancel_button"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -14,21 +14,21 @@
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@string/sas_verified"
tools:text="@string/sas_verified"
android:textColor="?riotx_text_primary"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/sas_verified" />
<TextView
android:id="@+id/verifyConclusionDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
tools:text="@string/sas_verified_successful_description"
android:text="@string/sas_verified_successful_description"
android:textColor="?riotx_text_secondary"
app:layout_constraintTop_toBottomOf="@id/verificationConclusionTitle"/>
app:layout_constraintTop_toBottomOf="@id/verificationConclusionTitle"
tools:text="@string/sas_verified_successful_description" />
<ImageView
android:id="@+id/verifyConclusionImageView"
@ -36,22 +36,20 @@
android:layout_height="180dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
tools:background="@drawable/ic_shield_trusted"
android:background="@drawable/ic_shield_trusted"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/verifyConclusionDescription" />
app:layout_constraintTop_toBottomOf="@id/verifyConclusionDescription"
tools:background="@drawable/ic_shield_trusted" />
<TextView
android:id="@+id/verifyConclusionBottomDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
tools:text="@string/verification_green_shield"
android:text="@string/verification_green_shield"
android:textColor="?riotx_text_secondary"
app:layout_constraintTop_toBottomOf="@id/verifyConclusionImageView"/>
app:layout_constraintTop_toBottomOf="@id/verifyConclusionImageView"
tools:text="@string/verification_green_shield" />
<com.google.android.material.button.MaterialButton

View file

@ -4,38 +4,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- <ImageView-->
<!-- android:id="@+id/verificationRequestAvatar"-->
<!-- android:layout_width="32dp"-->
<!-- android:layout_height="32dp"-->
<!-- android:adjustViewBounds="true"-->
<!-- android:background="@drawable/circle"-->
<!-- android:contentDescription="@string/avatar"-->
<!-- android:scaleType="centerCrop"-->
<!-- android:transitionName="bottomSheetAvatar"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"-->
<!-- app:layout_constraintVertical_bias="0"-->
<!-- tools:src="@tools:sample/avatars" />-->
<!-- <TextView-->
<!-- android:id="@+id/verificationRequestName"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginStart="16dp"-->
<!-- android:text="@string/verification_request_alert_title"-->
<!-- android:textColor="?riotx_text_primary"-->
<!-- android:textSize="20sp"-->
<!-- android:textStyle="bold"-->
<!-- android:transitionName="bottomSheetDisplayName"-->
<!-- app:layout_constraintBottom_toBottomOf="@id/verificationRequestAvatar"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toEndOf="@id/verificationRequestAvatar"-->
<!-- app:layout_constraintTop_toTopOf="@id/verificationRequestAvatar" />-->
<TextView
android:id="@+id/verificationRequestText"
android:layout_width="match_parent"
@ -53,8 +23,7 @@
android:layout_width="match_parent"
android:layout_marginTop="16dp"
android:text="@string/start_verification"
app:layout_constraintTop_toBottomOf="@id/verificationRequestText"
tools:visibility="visible" />
app:layout_constraintTop_toBottomOf="@id/verificationRequestText" />
<TextView
android:id="@+id/verificationWaitingText"
@ -65,6 +34,7 @@
android:textSize="17sp"
android:textStyle="bold"
android:visibility="invisible"
tools:visibility="visible"
app:layout_constraintBottom_toBottomOf="@id/verificationStartButton"
app:layout_constraintTop_toTopOf="@id/verificationStartButton"
tools:text="@string/verification_request_waiting_for" />

View file

@ -10,7 +10,7 @@
<string name="verification_conclusion_warning">Untrusted sign in</string>
<string name="verification_sas_match">They match</string>
<string name="verification_sas_do_not_match">They dont match</string>
<string name="verification_sas_do_not_match">They don\'t match</string>
<string name="verify_user_sas_emoji_help_text">Verify this user by confirming the following unique emoji appear on their screen, in the same order."</string>
<string name="verify_user_sas_emoji_security_tip">For ultimate security, use another trusted means of communication or do this in person.</string>
<string name="verification_green_shield">Look for the green shield to ensure a user is trusted. Trust all users in a room to ensure the room is secure.</string>
@ -31,4 +31,22 @@
<string name="verification_request_you_accepted">You accepted</string>
<string name="verification_sent">Verification Sent</string>
<string name="verification_request">Verification Request</string>
<!-- Sender name of a message when it is send by you, e.g. You: Hello!-->
<string name="you">You</string>
<string name="verify_by_scanning_title">Verify by scanning</string>
<!-- the %s will be replaced by verify_open_camera_link that will be clickable -->
<string name="verify_by_scanning_description">Ask the other user to scan this code, or %s to scan theirs</string>
<!-- This part is inserted in verify_by_scanning_description-->
<string name="verify_open_camera_link">open your camera</string>
<string name="verify_by_emoji_title">Verify by Emoji</string>
<string name="verify_by_emoji_description">If you cant scan the code above, verify by comparing a short, unique selection of emoji.</string>
<string name="aria_qr_code_description">QR code image</string>
<string name="verification_request_alert_title">Verify %s</string>
<string name="verification_request_waiting_for">Waiting for %s…</string>
<string name="verification_request_alert_description">For extra security, verify %s by checking a one-time code on both your devices.\n\nFor maximum security, do this in person.</string>
</resources>