From 12abca1b803e4efd8e6602881b49a5a15f057009 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 7 Apr 2020 19:09:56 +0200 Subject: [PATCH 01/20] Fix / Send gossip request on other done received --- .../crypto/gossiping/KeyShareTests.kt | 2 +- .../DefaultVerificationService.kt | 56 ++++++++++++++++++- .../DefaultVerificationTransaction.kt | 19 +++---- .../verification/VerificationInfoDone.kt | 8 +-- 4 files changed, 67 insertions(+), 18 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/gossiping/KeyShareTests.kt index 7ac92ed74c..bb6e020d89 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/gossiping/KeyShareTests.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/gossiping/KeyShareTests.kt @@ -282,7 +282,7 @@ class KeyShareTests : InstrumentedTest { val keysBackupService = aliceSession2.cryptoService().keysBackupService() mTestHelper.retryPeriodicallyWithLatch(latch) { Log.d("#TEST", "Recovery :${ keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey}") - keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey != creationInfo.recoveryKey + keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey == creationInfo.recoveryKey } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt index dc68fa6b76..db6c224019 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt @@ -22,6 +22,9 @@ import dagger.Lazy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService +import im.vector.matrix.android.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME +import im.vector.matrix.android.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME +import im.vector.matrix.android.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME import im.vector.matrix.android.api.session.crypto.verification.CancelCode import im.vector.matrix.android.api.session.crypto.verification.PendingVerificationRequest import im.vector.matrix.android.api.session.crypto.verification.QrCodeVerificationTransaction @@ -60,6 +63,7 @@ import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationAccept import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationCancel +import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationDone import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationKey import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationReady @@ -109,6 +113,10 @@ internal class DefaultVerificationService @Inject constructor( // map [sender : [transaction]] private val txMap = HashMap>() + // we need to keep track of finished transaction + // It will be used for gossiping (to send request after request is completed and 'done' by other) + private val pastTransactions = HashMap>() + /** * Map [sender: [PendingVerificationRequest]] * For now we keep all requests (even terminated ones) during the lifetime of the app. @@ -137,6 +145,9 @@ internal class DefaultVerificationService @Inject constructor( EventType.KEY_VERIFICATION_READY -> { onReadyReceived(event) } + EventType.KEY_VERIFICATION_DONE -> { + onDoneReceived(event) + } MessageType.MSGTYPE_VERIFICATION_REQUEST -> { onRequestReceived(event) } @@ -778,6 +789,31 @@ internal class DefaultVerificationService @Inject constructor( } } + private fun onDoneReceived(event: Event) { + Timber.v("## onDoneReceived") + val doneReq = event.getClearContent().toModel()?.asValidObject() + if (doneReq == null || event.senderId != userId) { + // ignore + Timber.e("## SAS Received invalid done request") + return + } + + // We only send gossiping request when the other sent us a done + // We can ask without checking too much thinks (like trust), because we will check validity of secret on reception + getExistingTransaction(userId, doneReq.transactionId) + ?: getOldTransaction(userId, doneReq.transactionId) + ?.let { vt -> + val otherDeviceId = vt.otherDeviceId + if (!crossSigningService.canCrossSign()) { + outgoingGossipingRequestManager.sendSecretShareRequest(SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId + ?: "*"))) + outgoingGossipingRequestManager.sendSecretShareRequest(USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId + ?: "*"))) + } + outgoingGossipingRequestManager.sendSecretShareRequest(KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) + } + } + private fun onRoomDoneReceived(event: Event) { val doneReq = event.getClearContent().toModel() ?.copy( @@ -1003,7 +1039,11 @@ internal class DefaultVerificationService @Inject constructor( private fun removeTransaction(otherUser: String, tid: String) { synchronized(txMap) { - txMap[otherUser]?.remove(tid)?.removeListener(this) + txMap[otherUser]?.remove(tid)?.also { + it.removeListener(this) + } + }?.let { + rememberOldTransaction(it) } } @@ -1016,6 +1056,20 @@ internal class DefaultVerificationService @Inject constructor( } } + private fun rememberOldTransaction(tx: DefaultVerificationTransaction) { + synchronized(pastTransactions) { + pastTransactions.getOrPut(tx.otherUserId) { HashMap() }[tx.transactionId] = tx + } + } + + private fun getOldTransaction(userId: String, tid: String?): DefaultVerificationTransaction? { + return tid?.let { + synchronized(pastTransactions) { + pastTransactions[userId]?.get(it) + } + } + } + override fun beginKeyVerification(method: VerificationMethod, otherUserId: String, otherDeviceId: String, transactionId: String?): String? { val txID = transactionId?.takeIf { it.isNotEmpty() } ?: createUniqueIDForTransaction(otherUserId, otherDeviceId) // should check if already one (and cancel it) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationTransaction.kt index 5b8191fc99..29cfcd2383 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationTransaction.kt @@ -17,9 +17,6 @@ package im.vector.matrix.android.internal.crypto.verification import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService -import im.vector.matrix.android.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME -import im.vector.matrix.android.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME -import im.vector.matrix.android.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME import im.vector.matrix.android.api.session.crypto.verification.VerificationTransaction import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState import im.vector.matrix.android.internal.crypto.IncomingGossipingRequestManager @@ -100,15 +97,15 @@ internal abstract class DefaultVerificationTransaction( }) } - transport.done(transactionId) { - if (otherUserId == userId && !crossSigningService.canCrossSign()) { - outgoingGossipingRequestManager.sendSecretShareRequest(SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) - outgoingGossipingRequestManager.sendSecretShareRequest(USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) - outgoingGossipingRequestManager.sendSecretShareRequest(KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) - } - } - state = VerificationTxState.Verified + + transport.done(transactionId) { +// if (otherUserId == userId && !crossSigningService.canCrossSign()) { +// outgoingGossipingRequestManager.sendSecretShareRequest(SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) +// outgoingGossipingRequestManager.sendSecretShareRequest(USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) +// outgoingGossipingRequestManager.sendSecretShareRequest(KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) +// } + } } private fun setDeviceVerified(userId: String, deviceId: String) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationInfoDone.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationInfoDone.kt index abb1141355..2986013fca 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationInfoDone.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationInfoDone.kt @@ -18,11 +18,9 @@ package im.vector.matrix.android.internal.crypto.verification internal interface VerificationInfoDone : VerificationInfo { override fun asValidObject(): ValidVerificationInfoDone? { - if (transactionId.isNullOrEmpty()) { - return null - } - return ValidVerificationInfoDone + val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null + return ValidVerificationInfoDone(validTransactionId) } } -internal object ValidVerificationInfoDone +internal data class ValidVerificationInfoDone(val transactionId: String) From b480eb36884c01cee41b044d16211bb3cb2d0da4 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 7 Apr 2020 19:20:49 +0200 Subject: [PATCH 02/20] Update change log --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 74269178dd..4dccae5ad5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Bugfix 🐛: - RiotX can't restore cross signing keys saved by web in SSSS (#1174) - Cross- Signing | After signin in new session, verification paper trail in DM is off (#1191) - Failed to encrypt message in room (message stays in red), [thanks to pwr22] (#925) + - Cross-Signing | web <-> riotX After QR code scan, gossiping fails (#1210) Translations 🗣: - From 68512e475ff6c71f90a7abede9a49210eb5a7ffe Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 7 Apr 2020 13:49:39 +0200 Subject: [PATCH 03/20] WIP --- .../timeline/TimelineEventController.kt | 4 +- .../factory/MergedHeaderItemFactory.kt | 78 +++++++++++++++++-- .../helper/TimelineDisplayableEvents.kt | 12 +++ .../detail/timeline/item/BasedMergedItem.kt | 63 +++++++++++++++ .../detail/timeline/item/MergedHeaderItem.kt | 41 +--------- 5 files changed, 152 insertions(+), 46 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BasedMergedItem.kt diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt index a8c9cf679b..48e92ca438 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt @@ -47,9 +47,9 @@ import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineEventVi import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider import im.vector.riotx.features.home.room.detail.timeline.helper.nextOrNull import im.vector.riotx.features.home.room.detail.timeline.item.BaseEventItem +import im.vector.riotx.features.home.room.detail.timeline.item.BasedMergedItem import im.vector.riotx.features.home.room.detail.timeline.item.DaySeparatorItem import im.vector.riotx.features.home.room.detail.timeline.item.DaySeparatorItem_ -import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData import im.vector.riotx.features.home.room.detail.timeline.item.TimelineReadMarkerItem_ @@ -373,7 +373,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec val localId: Long, val eventId: String?, val eventModel: EpoxyModel<*>? = null, - val mergedHeaderModel: MergedHeaderItem? = null, + val mergedHeaderModel: BasedMergedItem<*>? = null, val formattedDayModel: DaySeparatorItem? = null ) { fun shouldTriggerBuild(): Boolean { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt index 42dc4e07eb..a193efe076 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt @@ -16,6 +16,7 @@ package im.vector.riotx.features.home.room.detail.timeline.factory +import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.features.home.AvatarRenderer @@ -23,7 +24,10 @@ import im.vector.riotx.features.home.room.detail.timeline.TimelineEventControlle import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider import im.vector.riotx.features.home.room.detail.timeline.helper.MergedTimelineEventVisibilityStateChangedListener import im.vector.riotx.features.home.room.detail.timeline.helper.canBeMerged +import im.vector.riotx.features.home.room.detail.timeline.helper.isRoomConfiguration import im.vector.riotx.features.home.room.detail.timeline.helper.prevSameTypeEvents +import im.vector.riotx.features.home.room.detail.timeline.item.BaseEventItem +import im.vector.riotx.features.home.room.detail.timeline.item.BasedMergedItem import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem_ import javax.inject.Inject @@ -43,8 +47,72 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act eventIdToHighlight: String?, callback: TimelineEventController.Callback?, requestModelBuild: () -> Unit) - : MergedHeaderItem? { - return if (!event.canBeMerged() || (nextEvent?.root?.getClearType() == event.root.getClearType() && !addDaySeparator)) { + : BasedMergedItem<*>? { + return if (nextEvent?.root?.getClearType() == EventType.STATE_ROOM_CREATE && event.isRoomConfiguration()) { + // It's the first item before room.create + // Collapse all room configuration events + var prevEvent = if (currentPosition > 0) items[currentPosition -1] else null + var tmpPos = currentPosition -1 + val mergedEvents = ArrayList().also { it.add(event) } + while(prevEvent != null && prevEvent.isRoomConfiguration()) { + mergedEvents.add(prevEvent) + tmpPos-- + prevEvent = if (tmpPos >= 0) items[tmpPos] else null + } + if (mergedEvents.size > 2) { + var highlighted = false + val mergedData = ArrayList(mergedEvents.size) + mergedEvents.reversed() + .forEach { mergedEvent -> + if (!highlighted && mergedEvent.root.eventId == eventIdToHighlight) { + highlighted = true + } + val senderAvatar = mergedEvent.senderAvatar + val senderName = mergedEvent.getDisambiguatedDisplayName() + val data = BasedMergedItem.Data( + userId = mergedEvent.root.senderId ?: "", + avatarUrl = senderAvatar, + memberName = senderName, + localId = mergedEvent.localId, + eventId = mergedEvent.root.eventId ?: "" + ) + mergedData.add(data) + } + val mergedEventIds = mergedEvents.map { it.localId } + // We try to find if one of the item id were used as mergeItemCollapseStates key + // => handle case where paginating from mergeable events and we get more + val previousCollapseStateKey = mergedEventIds.intersect(mergeItemCollapseStates.keys).firstOrNull() + val initialCollapseState = mergeItemCollapseStates.remove(previousCollapseStateKey) + ?: true + val isCollapsed = mergeItemCollapseStates.getOrPut(event.localId) { initialCollapseState } + if (isCollapsed) { + collapsedEventIds.addAll(mergedEventIds) + } else { + collapsedEventIds.removeAll(mergedEventIds) + } + val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() } + val attributes = BasedMergedItem.Attributes( + isCollapsed = isCollapsed, + mergeData = mergedData, + avatarRenderer = avatarRenderer, + onCollapsedStateChanged = { + mergeItemCollapseStates[event.localId] = it + requestModelBuild() + }, + readReceiptsCallback = callback + ) + MergedHeaderItem_() + .id(mergeId) + .leftGuideline(avatarSizeProvider.leftGuideline) + .highlighted(isCollapsed && highlighted) + .attributes(attributes) + .also { + it.setOnVisibilityStateChanged(MergedTimelineEventVisibilityStateChangedListener(callback, mergedEvents)) + } + + } else null + } + else if (!event.canBeMerged() || (nextEvent?.root?.getClearType() == event.root.getClearType() && !addDaySeparator)) { null } else { val prevSameTypeEvents = items.prevSameTypeEvents(currentPosition, 2) @@ -53,14 +121,14 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act } else { var highlighted = false val mergedEvents = (prevSameTypeEvents + listOf(event)).asReversed() - val mergedData = ArrayList(mergedEvents.size) + val mergedData = ArrayList(mergedEvents.size) mergedEvents.forEach { mergedEvent -> if (!highlighted && mergedEvent.root.eventId == eventIdToHighlight) { highlighted = true } val senderAvatar = mergedEvent.senderAvatar val senderName = mergedEvent.getDisambiguatedDisplayName() - val data = MergedHeaderItem.Data( + val data = BasedMergedItem.Data( userId = mergedEvent.root.senderId ?: "", avatarUrl = senderAvatar, memberName = senderName, @@ -82,7 +150,7 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act collapsedEventIds.removeAll(mergedEventIds) } val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() } - val attributes = MergedHeaderItem.Attributes( + val attributes = BasedMergedItem.Attributes( isCollapsed = isCollapsed, mergeData = mergedData, avatarRenderer = avatarRenderer, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt index 5c763cb114..1ea3cd64ac 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt @@ -50,6 +50,18 @@ fun TimelineEvent.canBeMerged(): Boolean { return root.getClearType() == EventType.STATE_ROOM_MEMBER } +fun TimelineEvent.isRoomConfiguration(): Boolean { + return when (root.getClearType()) { + EventType.STATE_ROOM_GUEST_ACCESS, + EventType.STATE_ROOM_HISTORY_VISIBILITY, + EventType.STATE_ROOM_JOIN_RULES, + EventType.STATE_ROOM_MEMBER, + EventType.STATE_ROOM_NAME, + EventType.STATE_ROOM_ENCRYPTION -> true + else -> false + } +} + fun List.nextSameTypeEvents(index: Int, minSize: Int): List { if (index >= size - 1) { return emptyList() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BasedMergedItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BasedMergedItem.kt new file mode 100644 index 0000000000..832b4017a7 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BasedMergedItem.kt @@ -0,0 +1,63 @@ +/* + * 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.riotx.features.home.room.detail.timeline.item + +import androidx.annotation.IdRes +import com.airbnb.epoxy.EpoxyAttribute +import im.vector.matrix.android.api.util.MatrixItem +import im.vector.riotx.features.home.AvatarRenderer +import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController + +abstract class BasedMergedItem : BaseEventItem() { + + @EpoxyAttribute + lateinit var attributes: Attributes + + protected val distinctMergeData by lazy { + attributes.mergeData.distinctBy { it.userId } + } + + override fun getEventIds(): List { + return if (attributes.isCollapsed) { + attributes.mergeData.map { it.eventId } + } else { + emptyList() + } + } + + data class Data( + val localId: Long, + val eventId: String, + val userId: String, + val memberName: String, + val avatarUrl: String? + ) + + fun Data.toMatrixItem() = MatrixItem.UserItem(userId, memberName, avatarUrl) + + data class Attributes( + val isCollapsed: Boolean, + val mergeData: List, + val avatarRenderer: AvatarRenderer, + val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null, + val onCollapsedStateChanged: (Boolean) -> Unit + ) + + abstract class Holder(@IdRes stubId: Int) : BaseEventItem.BaseHolder(stubId) { + //val reactionsContainer by bind(R.id.reactionsContainer) + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt index 93f7dc271d..2d6bb0f85d 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt @@ -22,22 +22,11 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.view.children import androidx.core.view.isVisible -import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass -import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R -import im.vector.riotx.features.home.AvatarRenderer -import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController @EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo) -abstract class MergedHeaderItem : BaseEventItem() { - - @EpoxyAttribute - lateinit var attributes: Attributes - - private val distinctMergeData by lazy { - attributes.mergeData.distinctBy { it.userId } - } +abstract class MergedHeaderItem : BasedMergedItem() { override fun getViewType() = STUB_ID @@ -72,33 +61,7 @@ abstract class MergedHeaderItem : BaseEventItem() { holder.readReceiptsView.isVisible = false } - override fun getEventIds(): List { - return if (attributes.isCollapsed) { - attributes.mergeData.map { it.eventId } - } else { - emptyList() - } - } - - data class Data( - val localId: Long, - val eventId: String, - val userId: String, - val memberName: String, - val avatarUrl: String? - ) - - fun Data.toMatrixItem() = MatrixItem.UserItem(userId, memberName, avatarUrl) - - data class Attributes( - val isCollapsed: Boolean, - val mergeData: List, - val avatarRenderer: AvatarRenderer, - val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null, - val onCollapsedStateChanged: (Boolean) -> Unit - ) - - class Holder : BaseHolder(STUB_ID) { + class Holder : BasedMergedItem.Holder(STUB_ID) { val expandView by bind(R.id.itemMergedExpandTextView) val summaryView by bind(R.id.itemMergedSummaryTextView) val separatorView by bind(R.id.itemMergedSeparatorView) From 277f35a352f57047881b2fe1d2e061ad0a549a23 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 8 Apr 2020 14:39:57 +0200 Subject: [PATCH 04/20] Merge room creation events in one summary --- .../timeline/factory/EncryptionItemFactory.kt | 81 ++++++++++ .../factory/MergedHeaderItemFactory.kt | 142 ++++++++++-------- .../timeline/factory/TimelineItemFactory.kt | 7 +- .../factory/VerificationItemFactory.kt | 27 ++-- .../detail/timeline/item/BasedMergedItem.kt | 41 +++-- .../detail/timeline/item/MergedHeaderItem.kt | 23 +-- .../timeline/item/MergedRoomCreationItem.kt | 118 +++++++++++++++ ...usionItem.kt => StatusTileTimelineItem.kt} | 27 +++- .../item_timeline_event_base_noinfo.xml | 7 + ...meline_event_merged_room_creation_stub.xml | 80 ++++++++++ vector/src/main/res/values/strings_riotX.xml | 7 + 11 files changed, 454 insertions(+), 106 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt rename vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/{VerificationRequestConclusionItem.kt => StatusTileTimelineItem.kt} (82%) create mode 100644 vector/src/main/res/layout/item_timeline_event_merged_room_creation_stub.xml diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt new file mode 100644 index 0000000000..a175fc6e84 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt @@ -0,0 +1,81 @@ +/* + * 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.riotx.features.home.room.detail.timeline.factory + +import im.vector.matrix.android.api.session.events.model.toModel +import im.vector.matrix.android.api.session.room.timeline.TimelineEvent +import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent +import im.vector.riotx.R +import im.vector.riotx.core.resources.StringProvider +import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider +import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController +import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider +import im.vector.riotx.features.home.room.detail.timeline.helper.MessageInformationDataFactory +import im.vector.riotx.features.home.room.detail.timeline.helper.MessageItemAttributesFactory +import im.vector.riotx.features.home.room.detail.timeline.item.StatusTileTimelineItem +import im.vector.riotx.features.home.room.detail.timeline.item.StatusTileTimelineItem_ +import javax.inject.Inject + +class EncryptionItemFactory @Inject constructor( + private val messageItemAttributesFactory: MessageItemAttributesFactory, + private val messageColorProvider: MessageColorProvider, + private val stringProvider: StringProvider, + private val informationDataFactory: MessageInformationDataFactory, + private val avatarSizeProvider: AvatarSizeProvider) { + + fun create(event: TimelineEvent, + highlight: Boolean, + callback: TimelineEventController.Callback?): StatusTileTimelineItem? { + + val algorithm = event.root.getClearContent().toModel()?.algorithm + val informationData = informationDataFactory.create(event, null) + val attributes = messageItemAttributesFactory.create(null, informationData, callback) + + val isSafeAlgorithm = algorithm == MXCRYPTO_ALGORITHM_MEGOLM + val title: String + val description: String + val shield: StatusTileTimelineItem.ShieldUIState + if (isSafeAlgorithm) { + title = stringProvider.getString(R.string.encryption_enabled) + description = stringProvider.getString(R.string.encryption_enabled_tile_description) + shield = StatusTileTimelineItem.ShieldUIState.BLACK + } else { + title = stringProvider.getString(R.string.encryption_not_enabled) + description = stringProvider.getString(R.string.encryption_unknown_algorithm_tile_description) + shield = StatusTileTimelineItem.ShieldUIState.RED + } + return StatusTileTimelineItem_() + .attributes( + StatusTileTimelineItem.Attributes( + title = title, + description = description, + shieldUIState = shield, + informationData = informationData, + avatarRenderer = attributes.avatarRenderer, + messageColorProvider = messageColorProvider, + emojiTypeFace = attributes.emojiTypeFace, + itemClickListener = attributes.itemClickListener, + itemLongClickListener = attributes.itemLongClickListener, + reactionPillCallback = attributes.reactionPillCallback, + readReceiptsCallback = attributes.readReceiptsCallback + ) + ) + .highlighted(highlight) + .leftGuideline(avatarSizeProvider.leftGuideline) + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt index a193efe076..3d95d1d49b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt @@ -17,7 +17,10 @@ package im.vector.riotx.features.home.room.detail.timeline.factory import im.vector.matrix.android.api.session.events.model.EventType +import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.timeline.TimelineEvent +import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController @@ -26,10 +29,11 @@ import im.vector.riotx.features.home.room.detail.timeline.helper.MergedTimelineE import im.vector.riotx.features.home.room.detail.timeline.helper.canBeMerged import im.vector.riotx.features.home.room.detail.timeline.helper.isRoomConfiguration import im.vector.riotx.features.home.room.detail.timeline.helper.prevSameTypeEvents -import im.vector.riotx.features.home.room.detail.timeline.item.BaseEventItem import im.vector.riotx.features.home.room.detail.timeline.item.BasedMergedItem import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem_ +import im.vector.riotx.features.home.room.detail.timeline.item.MergedRoomCreationItem +import im.vector.riotx.features.home.room.detail.timeline.item.MergedRoomCreationItem_ import javax.inject.Inject class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: ActiveSessionHolder, @@ -51,68 +55,8 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act return if (nextEvent?.root?.getClearType() == EventType.STATE_ROOM_CREATE && event.isRoomConfiguration()) { // It's the first item before room.create // Collapse all room configuration events - var prevEvent = if (currentPosition > 0) items[currentPosition -1] else null - var tmpPos = currentPosition -1 - val mergedEvents = ArrayList().also { it.add(event) } - while(prevEvent != null && prevEvent.isRoomConfiguration()) { - mergedEvents.add(prevEvent) - tmpPos-- - prevEvent = if (tmpPos >= 0) items[tmpPos] else null - } - if (mergedEvents.size > 2) { - var highlighted = false - val mergedData = ArrayList(mergedEvents.size) - mergedEvents.reversed() - .forEach { mergedEvent -> - if (!highlighted && mergedEvent.root.eventId == eventIdToHighlight) { - highlighted = true - } - val senderAvatar = mergedEvent.senderAvatar - val senderName = mergedEvent.getDisambiguatedDisplayName() - val data = BasedMergedItem.Data( - userId = mergedEvent.root.senderId ?: "", - avatarUrl = senderAvatar, - memberName = senderName, - localId = mergedEvent.localId, - eventId = mergedEvent.root.eventId ?: "" - ) - mergedData.add(data) - } - val mergedEventIds = mergedEvents.map { it.localId } - // We try to find if one of the item id were used as mergeItemCollapseStates key - // => handle case where paginating from mergeable events and we get more - val previousCollapseStateKey = mergedEventIds.intersect(mergeItemCollapseStates.keys).firstOrNull() - val initialCollapseState = mergeItemCollapseStates.remove(previousCollapseStateKey) - ?: true - val isCollapsed = mergeItemCollapseStates.getOrPut(event.localId) { initialCollapseState } - if (isCollapsed) { - collapsedEventIds.addAll(mergedEventIds) - } else { - collapsedEventIds.removeAll(mergedEventIds) - } - val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() } - val attributes = BasedMergedItem.Attributes( - isCollapsed = isCollapsed, - mergeData = mergedData, - avatarRenderer = avatarRenderer, - onCollapsedStateChanged = { - mergeItemCollapseStates[event.localId] = it - requestModelBuild() - }, - readReceiptsCallback = callback - ) - MergedHeaderItem_() - .id(mergeId) - .leftGuideline(avatarSizeProvider.leftGuideline) - .highlighted(isCollapsed && highlighted) - .attributes(attributes) - .also { - it.setOnVisibilityStateChanged(MergedTimelineEventVisibilityStateChangedListener(callback, mergedEvents)) - } - - } else null - } - else if (!event.canBeMerged() || (nextEvent?.root?.getClearType() == event.root.getClearType() && !addDaySeparator)) { + buildRoomCreationMergedSummary(currentPosition, items, event, eventIdToHighlight, requestModelBuild, callback) + } else if (!event.canBeMerged() || (nextEvent?.root?.getClearType() == event.root.getClearType() && !addDaySeparator)) { null } else { val prevSameTypeEvents = items.prevSameTypeEvents(currentPosition, 2) @@ -150,7 +94,7 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act collapsedEventIds.removeAll(mergedEventIds) } val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() } - val attributes = BasedMergedItem.Attributes( + val attributes = MergedHeaderItem.Attributes( isCollapsed = isCollapsed, mergeData = mergedData, avatarRenderer = avatarRenderer, @@ -172,6 +116,76 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act } } + private fun buildRoomCreationMergedSummary(currentPosition: Int, items: List, event: TimelineEvent, eventIdToHighlight: String?, requestModelBuild: () -> Unit, callback: TimelineEventController.Callback?): MergedRoomCreationItem_? { + var prevEvent = if (currentPosition > 0) items[currentPosition - 1] else null + var tmpPos = currentPosition - 1 + val mergedEvents = ArrayList().also { it.add(event) } + var hasEncryption = false + var encryptionAlgorithm: String? = null + while (prevEvent != null && prevEvent.isRoomConfiguration()) { + if (prevEvent.root.getClearType() == EventType.STATE_ROOM_ENCRYPTION) { + hasEncryption = true + encryptionAlgorithm = prevEvent.root.getClearContent()?.toModel()?.algorithm + } + mergedEvents.add(prevEvent) + tmpPos-- + prevEvent = if (tmpPos >= 0) items[tmpPos] else null + } + return if (mergedEvents.size > 2) { + var highlighted = false + val mergedData = ArrayList(mergedEvents.size) + mergedEvents.reversed() + .forEach { mergedEvent -> + if (!highlighted && mergedEvent.root.eventId == eventIdToHighlight) { + highlighted = true + } + val senderAvatar = mergedEvent.senderAvatar + val senderName = mergedEvent.getDisambiguatedDisplayName() + val data = BasedMergedItem.Data( + userId = mergedEvent.root.senderId ?: "", + avatarUrl = senderAvatar, + memberName = senderName, + localId = mergedEvent.localId, + eventId = mergedEvent.root.eventId ?: "" + ) + mergedData.add(data) + } + val mergedEventIds = mergedEvents.map { it.localId } + // We try to find if one of the item id were used as mergeItemCollapseStates key + // => handle case where paginating from mergeable events and we get more + val previousCollapseStateKey = mergedEventIds.intersect(mergeItemCollapseStates.keys).firstOrNull() + val initialCollapseState = mergeItemCollapseStates.remove(previousCollapseStateKey) + ?: true + val isCollapsed = mergeItemCollapseStates.getOrPut(event.localId) { initialCollapseState } + if (isCollapsed) { + collapsedEventIds.addAll(mergedEventIds) + } else { + collapsedEventIds.removeAll(mergedEventIds) + } + val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() } + val attributes = MergedRoomCreationItem.Attributes( + isCollapsed = isCollapsed, + mergeData = mergedData, + avatarRenderer = avatarRenderer, + onCollapsedStateChanged = { + mergeItemCollapseStates[event.localId] = it + requestModelBuild() + }, + hasEncryptionEvent = hasEncryption, + isEncryptionAlgorithmSecure = encryptionAlgorithm == MXCRYPTO_ALGORITHM_MEGOLM, + readReceiptsCallback = callback + ) + MergedRoomCreationItem_() + .id(mergeId) + .leftGuideline(avatarSizeProvider.leftGuideline) + .highlighted(isCollapsed && highlighted) + .attributes(attributes) + .also { + it.setOnVisibilityStateChanged(MergedTimelineEventVisibilityStateChangedListener(callback, mergedEvents)) + } + } else null + } + fun isCollapsed(localId: Long): Boolean { return collapsedEventIds.contains(localId) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt index 1462f5fe0d..7e6c387934 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt @@ -29,6 +29,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me private val encryptedItemFactory: EncryptedItemFactory, private val noticeItemFactory: NoticeItemFactory, private val defaultItemFactory: DefaultItemFactory, + private val encryptionItemFactory: EncryptionItemFactory, private val roomCreateItemFactory: RoomCreateItemFactory, private val verificationConclusionItemFactory: VerificationItemFactory, private val userPreferencesProvider: UserPreferencesProvider) { @@ -57,8 +58,10 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me EventType.CALL_HANGUP, EventType.CALL_ANSWER, EventType.REACTION, - EventType.REDACTION, - EventType.STATE_ROOM_ENCRYPTION -> noticeItemFactory.create(event, highlight, callback) + EventType.REDACTION -> noticeItemFactory.create(event, highlight, callback) + EventType.STATE_ROOM_ENCRYPTION -> { + encryptionItemFactory.create(event, highlight, callback) + } // State room create EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback) // Crypto diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt index ee529282f9..3aa43120ea 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt @@ -25,15 +25,17 @@ import im.vector.matrix.android.api.session.room.model.message.MessageRelationCo import im.vector.matrix.android.api.session.room.model.message.MessageVerificationCancelContent import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.internal.session.room.VerificationState +import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyModel +import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.UserPreferencesProvider import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider import im.vector.riotx.features.home.room.detail.timeline.helper.MessageInformationDataFactory import im.vector.riotx.features.home.room.detail.timeline.helper.MessageItemAttributesFactory -import im.vector.riotx.features.home.room.detail.timeline.item.VerificationRequestConclusionItem -import im.vector.riotx.features.home.room.detail.timeline.item.VerificationRequestConclusionItem_ +import im.vector.riotx.features.home.room.detail.timeline.item.StatusTileTimelineItem +import im.vector.riotx.features.home.room.detail.timeline.item.StatusTileTimelineItem_ import javax.inject.Inject /** @@ -48,6 +50,7 @@ class VerificationItemFactory @Inject constructor( private val avatarSizeProvider: AvatarSizeProvider, private val noticeItemFactory: NoticeItemFactory, private val userPreferencesProvider: UserPreferencesProvider, + private val stringProvider: StringProvider, private val session: Session ) { @@ -88,12 +91,12 @@ class VerificationItemFactory @Inject constructor( CancelCode.MismatchedKeys, CancelCode.MismatchedSas -> { // We should display these bad conclusions - return VerificationRequestConclusionItem_() + return StatusTileTimelineItem_() .attributes( - VerificationRequestConclusionItem.Attributes( - toUserId = informationData.senderId, - toUserName = informationData.memberName.toString(), - isPositive = false, + StatusTileTimelineItem.Attributes( + title = stringProvider.getString(R.string.verification_conclusion_warning), + description = "${informationData.memberName.toString()} (${informationData.senderId})", + shieldUIState = StatusTileTimelineItem.ShieldUIState.RED, informationData = informationData, avatarRenderer = attributes.avatarRenderer, messageColorProvider = messageColorProvider, @@ -121,12 +124,12 @@ class VerificationItemFactory @Inject constructor( // We only display the done sent by the other user, the done send by me is ignored return ignoredConclusion(event, highlight, callback) } - return VerificationRequestConclusionItem_() + return StatusTileTimelineItem_() .attributes( - VerificationRequestConclusionItem.Attributes( - toUserId = informationData.senderId, - toUserName = informationData.memberName.toString(), - isPositive = true, + StatusTileTimelineItem.Attributes( + title = stringProvider.getString(R.string.sas_verified), + description = "${informationData.memberName.toString()} (${informationData.senderId})", + shieldUIState = StatusTileTimelineItem.ShieldUIState.GREEN, informationData = informationData, avatarRenderer = attributes.avatarRenderer, messageColorProvider = messageColorProvider, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BasedMergedItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BasedMergedItem.kt index 832b4017a7..adc9b1442f 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BasedMergedItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BasedMergedItem.kt @@ -16,16 +16,34 @@ package im.vector.riotx.features.home.room.detail.timeline.item +import android.view.View +import android.widget.TextView import androidx.annotation.IdRes -import com.airbnb.epoxy.EpoxyAttribute +import androidx.core.view.isVisible import im.vector.matrix.android.api.util.MatrixItem +import im.vector.riotx.R import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController abstract class BasedMergedItem : BaseEventItem() { - @EpoxyAttribute - lateinit var attributes: Attributes + abstract val attributes: Attributes + + override fun bind(holder: H) { + super.bind(holder) + holder.expandView.setOnClickListener { + attributes.onCollapsedStateChanged(!attributes.isCollapsed) + } + if (attributes.isCollapsed) { + holder.separatorView.visibility = View.GONE + holder.expandView.setText(R.string.merged_events_expand) + } else { + holder.separatorView.visibility = View.VISIBLE + holder.expandView.setText(R.string.merged_events_collapse) + } + // No read receipt for this item + holder.readReceiptsView.isVisible = false + } protected val distinctMergeData by lazy { attributes.mergeData.distinctBy { it.userId } @@ -49,15 +67,16 @@ abstract class BasedMergedItem : BaseEventItem() fun Data.toMatrixItem() = MatrixItem.UserItem(userId, memberName, avatarUrl) - data class Attributes( - val isCollapsed: Boolean, - val mergeData: List, - val avatarRenderer: AvatarRenderer, - val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null, - val onCollapsedStateChanged: (Boolean) -> Unit - ) + interface Attributes { + val isCollapsed: Boolean + val mergeData: List + val avatarRenderer: AvatarRenderer + val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? + val onCollapsedStateChanged: (Boolean) -> Unit + } abstract class Holder(@IdRes stubId: Int) : BaseEventItem.BaseHolder(stubId) { - //val reactionsContainer by bind(R.id.reactionsContainer) + val expandView by bind(R.id.itemMergedExpandTextView) + val separatorView by bind(R.id.itemMergedSeparatorView) } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt index 2d6bb0f85d..59f4d08d68 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt @@ -22,19 +22,22 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.view.children import androidx.core.view.isVisible +import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R +import im.vector.riotx.features.home.AvatarRenderer +import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController @EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo) abstract class MergedHeaderItem : BasedMergedItem() { override fun getViewType() = STUB_ID + @EpoxyAttribute + override lateinit var attributes: Attributes + override fun bind(holder: Holder) { super.bind(holder) - holder.expandView.setOnClickListener { - attributes.onCollapsedStateChanged(!attributes.isCollapsed) - } if (attributes.isCollapsed) { val summary = holder.expandView.resources.getQuantityString(R.plurals.membership_changes, attributes.mergeData.size, attributes.mergeData.size) holder.summaryView.text = summary @@ -49,26 +52,28 @@ abstract class MergedHeaderItem : BasedMergedItem() { view.visibility = View.GONE } } - holder.separatorView.visibility = View.GONE - holder.expandView.setText(R.string.merged_events_expand) } else { holder.avatarListView.visibility = View.INVISIBLE holder.summaryView.visibility = View.GONE - holder.separatorView.visibility = View.VISIBLE - holder.expandView.setText(R.string.merged_events_collapse) } // No read receipt for this item holder.readReceiptsView.isVisible = false } class Holder : BasedMergedItem.Holder(STUB_ID) { - val expandView by bind(R.id.itemMergedExpandTextView) val summaryView by bind(R.id.itemMergedSummaryTextView) - val separatorView by bind(R.id.itemMergedSeparatorView) val avatarListView by bind(R.id.itemMergedAvatarListView) } companion object { private const val STUB_ID = R.id.messageContentMergedHeaderStub } + + data class Attributes( + override val isCollapsed: Boolean, + override val mergeData: List, + override val avatarRenderer: AvatarRenderer, + override val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null, + override val onCollapsedStateChanged: (Boolean) -> Unit + ) : BasedMergedItem.Attributes } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt new file mode 100644 index 0000000000..78e6ffe67b --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt @@ -0,0 +1,118 @@ +/* + * 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.riotx.features.home.room.detail.timeline.item + +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.core.view.isGone +import androidx.core.view.isVisible +import androidx.core.view.marginLeft +import androidx.core.view.updateLayoutParams +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.riotx.R +import im.vector.riotx.features.home.AvatarRenderer +import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController +import org.w3c.dom.Text + +@EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo) +abstract class MergedRoomCreationItem : BasedMergedItem() { + + @EpoxyAttribute + override lateinit var attributes: Attributes + + override fun getViewType() = STUB_ID + + override fun bind(holder: Holder) { + super.bind(holder) + + if (attributes.isCollapsed) { + + val data = distinctMergeData.firstOrNull() + + val summary = holder.expandView.resources.getString(R.string.room_created_summary_item, + data?.memberName ?: data?.userId ?: "") + holder.summaryView.text = summary + holder.summaryView.visibility = View.VISIBLE + holder.avatarView.visibility = View.VISIBLE + if (data != null) { + holder.avatarView.visibility = View.VISIBLE + attributes.avatarRenderer.render(data.toMatrixItem(), holder.avatarView) + } else { + holder.avatarView.visibility = View.GONE + } + + if (attributes.hasEncryptionEvent) { + holder.encryptionTile.isVisible = true + holder.encryptionTile.updateLayoutParams { + this.marginEnd = leftGuideline + } + if (attributes.isEncryptionAlgorithmSecure) { + holder.e2eTitleTextView.text = holder.expandView.resources.getString(R.string.encryption_enabled) + holder.e2eTitleDescriptionView.text = holder.expandView.resources.getString(R.string.encryption_enabled_tile_description) + holder.e2eTitleDescriptionView.textAlignment = View.TEXT_ALIGNMENT_CENTER + holder.e2eTitleTextView.setCompoundDrawablesWithIntrinsicBounds( + ContextCompat.getDrawable(holder.view.context, R.drawable.ic_shield_black), + null, null, null + ) + } else { + holder.e2eTitleTextView.text = holder.expandView.resources.getString(R.string.encryption_not_enabled) + holder.e2eTitleDescriptionView.text = holder.expandView.resources.getString(R.string.encryption_unknown_algorithm_tile_description) + holder.e2eTitleTextView.setCompoundDrawablesWithIntrinsicBounds( + ContextCompat.getDrawable(holder.view.context, R.drawable.ic_shield_warning), + null, null, null + ) + } + } else { + holder.encryptionTile.isVisible = false + } + } else { + holder.avatarView.visibility = View.INVISIBLE + holder.summaryView.visibility = View.GONE + holder.encryptionTile.isGone = true + } + // No read receipt for this item + holder.readReceiptsView.isVisible = false + } + + class Holder : BasedMergedItem.Holder(STUB_ID) { + val summaryView by bind(R.id.itemNoticeTextView) + val avatarView by bind(R.id.itemNoticeAvatarView) + val encryptionTile by bind(R.id.creationEncryptionTile) + + val e2eTitleTextView by bind(R.id.itemVerificationDoneTitleTextView) + val e2eTitleDescriptionView by bind(R.id.itemVerificationDoneDetailTextView) + } + + companion object { + private const val STUB_ID = R.id.messageContentMergedCreationStub + } + + data class Attributes( + override val isCollapsed: Boolean, + override val mergeData: List, + override val avatarRenderer: AvatarRenderer, + override val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null, + override val onCollapsedStateChanged: (Boolean) -> Unit, + val hasEncryptionEvent : Boolean, + val isEncryptionAlgorithmSecure: Boolean + ) : BasedMergedItem.Attributes +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/VerificationRequestConclusionItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt similarity index 82% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/VerificationRequestConclusionItem.kt rename to vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt index 2b28e15cab..79ffb3a6eb 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/VerificationRequestConclusionItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt @@ -31,7 +31,7 @@ import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController @EpoxyModelClass(layout = R.layout.item_timeline_event_base_state) -abstract class VerificationRequestConclusionItem : AbsBaseMessageItem() { +abstract class StatusTileTimelineItem : AbsBaseMessageItem() { override val baseAttributes: AbsBaseMessageItem.Attributes get() = attributes @@ -47,11 +47,16 @@ abstract class VerificationRequestConclusionItem : AbsBaseMessageItem { this.marginEnd = leftGuideline } - val title = if (attributes.isPositive) R.string.sas_verified else R.string.verification_conclusion_warning - holder.titleView.text = holder.view.context.getString(title) - holder.descriptionView.text = "${attributes.informationData.memberName} (${attributes.informationData.senderId})" - val startDrawable = if (attributes.isPositive) R.drawable.ic_shield_trusted else R.drawable.ic_shield_warning + holder.titleView.text = attributes.title + holder.descriptionView.text = attributes.description + + val startDrawable = when (attributes.shieldUIState) { + ShieldUIState.GREEN -> R.drawable.ic_shield_trusted + ShieldUIState.BLACK -> R.drawable.ic_shield_black + ShieldUIState.RED -> R.drawable.ic_shield_warning + } + holder.titleView.setCompoundDrawablesWithIntrinsicBounds( ContextCompat.getDrawable(holder.view.context, startDrawable), null, null, null @@ -75,9 +80,9 @@ abstract class VerificationRequestConclusionItem : AbsBaseMessageItem + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 29e57d1133..606a1b95f6 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -87,6 +87,13 @@ Setting a Message Password lets you secure & unlock encrypted messages and trust.\n\nIf you don’t want to set a Message Password, generate a Message Key instead. Setting a Message Password lets you secure & unlock encrypted messages and trust. + + Encryption enabled + Messages in this room are end-to-end encrypted. Learn more & verify users in their profile. + Encryption not enabled + The encryption used by this room is not supported + + %s created and configured the room. From 08af61b77819cbe5725ca6731857cec2aa6d54d1 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 8 Apr 2020 14:41:57 +0200 Subject: [PATCH 05/20] rename layout --- vector/src/main/res/layout/item_timeline_event_base_state.xml | 2 +- .../layout/item_timeline_event_merged_room_creation_stub.xml | 2 +- ...n_done_stub.xml => item_timeline_event_status_tile_stub.xml} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename vector/src/main/res/layout/{item_timeline_event_verification_done_stub.xml => item_timeline_event_status_tile_stub.xml} (100%) diff --git a/vector/src/main/res/layout/item_timeline_event_base_state.xml b/vector/src/main/res/layout/item_timeline_event_base_state.xml index 5ad58b5201..af20c3f549 100644 --- a/vector/src/main/res/layout/item_timeline_event_base_state.xml +++ b/vector/src/main/res/layout/item_timeline_event_base_state.xml @@ -49,7 +49,7 @@ diff --git a/vector/src/main/res/layout/item_timeline_event_merged_room_creation_stub.xml b/vector/src/main/res/layout/item_timeline_event_merged_room_creation_stub.xml index 56f38f2276..3ed840954f 100644 --- a/vector/src/main/res/layout/item_timeline_event_merged_room_creation_stub.xml +++ b/vector/src/main/res/layout/item_timeline_event_merged_room_creation_stub.xml @@ -17,7 +17,7 @@ android:background="@drawable/rounded_rect_shape_8" android:padding="8dp"> - + diff --git a/vector/src/main/res/layout/item_timeline_event_verification_done_stub.xml b/vector/src/main/res/layout/item_timeline_event_status_tile_stub.xml similarity index 100% rename from vector/src/main/res/layout/item_timeline_event_verification_done_stub.xml rename to vector/src/main/res/layout/item_timeline_event_status_tile_stub.xml From f04d8b0e03c0099592d91da3b127c9117bb92346 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 8 Apr 2020 14:43:32 +0200 Subject: [PATCH 06/20] cleaning --- .../room/detail/timeline/factory/EncryptionItemFactory.kt | 1 - .../detail/timeline/factory/MergedHeaderItemFactory.kt | 7 ++++++- .../detail/timeline/factory/VerificationItemFactory.kt | 4 ++-- .../room/detail/timeline/item/MergedRoomCreationItem.kt | 3 --- .../room/detail/timeline/item/StatusTileTimelineItem.kt | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt index a175fc6e84..ff65b0e656 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt @@ -41,7 +41,6 @@ class EncryptionItemFactory @Inject constructor( fun create(event: TimelineEvent, highlight: Boolean, callback: TimelineEventController.Callback?): StatusTileTimelineItem? { - val algorithm = event.root.getClearContent().toModel()?.algorithm val informationData = informationDataFactory.create(event, null) val attributes = messageItemAttributesFactory.create(null, informationData, callback) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt index 3d95d1d49b..00e90558a6 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt @@ -116,7 +116,12 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act } } - private fun buildRoomCreationMergedSummary(currentPosition: Int, items: List, event: TimelineEvent, eventIdToHighlight: String?, requestModelBuild: () -> Unit, callback: TimelineEventController.Callback?): MergedRoomCreationItem_? { + private fun buildRoomCreationMergedSummary(currentPosition: Int, + items: List, + event: TimelineEvent, + eventIdToHighlight: String?, + requestModelBuild: () -> Unit, + callback: TimelineEventController.Callback?): MergedRoomCreationItem_? { var prevEvent = if (currentPosition > 0) items[currentPosition - 1] else null var tmpPos = currentPosition - 1 val mergedEvents = ArrayList().also { it.add(event) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt index 3aa43120ea..837d0ad571 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt @@ -95,7 +95,7 @@ class VerificationItemFactory @Inject constructor( .attributes( StatusTileTimelineItem.Attributes( title = stringProvider.getString(R.string.verification_conclusion_warning), - description = "${informationData.memberName.toString()} (${informationData.senderId})", + description = "${informationData.memberName} (${informationData.senderId})", shieldUIState = StatusTileTimelineItem.ShieldUIState.RED, informationData = informationData, avatarRenderer = attributes.avatarRenderer, @@ -128,7 +128,7 @@ class VerificationItemFactory @Inject constructor( .attributes( StatusTileTimelineItem.Attributes( title = stringProvider.getString(R.string.sas_verified), - description = "${informationData.memberName.toString()} (${informationData.senderId})", + description = "${informationData.memberName} (${informationData.senderId})", shieldUIState = StatusTileTimelineItem.ShieldUIState.GREEN, informationData = informationData, avatarRenderer = attributes.avatarRenderer, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt index 78e6ffe67b..81050194a8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt @@ -24,14 +24,12 @@ import android.widget.TextView import androidx.core.content.ContextCompat import androidx.core.view.isGone import androidx.core.view.isVisible -import androidx.core.view.marginLeft import androidx.core.view.updateLayoutParams import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController -import org.w3c.dom.Text @EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo) abstract class MergedRoomCreationItem : BasedMergedItem() { @@ -45,7 +43,6 @@ abstract class MergedRoomCreationItem : BasedMergedItem R.drawable.ic_shield_black ShieldUIState.RED -> R.drawable.ic_shield_warning } - + holder.titleView.setCompoundDrawablesWithIntrinsicBounds( ContextCompat.getDrawable(holder.view.context, startDrawable), null, null, null From aec49fe542fc6a98e71fa1f1662f10af58707819 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 8 Apr 2020 14:56:37 +0200 Subject: [PATCH 07/20] Change log --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 4dccae5ad5..983c9841cd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,12 +6,14 @@ Features ✨: - Cross-Signing | Verify new session from existing session (#1134) - Cross-Signing | Bootstraping cross signing with 4S from mobile (#985) + Improvements 🙌: - Verification DM / Handle concurrent .start after .ready (#794) - Cross-Signing | Update Shield Logic for DM (#963) - Cross-Signing | Complete security new session design update (#1135) - Cross-Signing | Setup key backup as part of SSSS bootstrapping (#1201) - Cross-Signing | Gossip key backup recovery key (#1200) + - Show room encryption status as a bubble tile (#1078) Bugfix 🐛: - Missing avatar/displayname after verification request message (#841) From 366a35913b4833ecb9e0c8dc6efe7e2ab585dcf6 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 8 Apr 2020 15:05:49 +0200 Subject: [PATCH 08/20] Fix alignement --- .../home/room/detail/timeline/item/StatusTileTimelineItem.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt index 43c53c7267..f9ea2a71df 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt @@ -50,6 +50,7 @@ abstract class StatusTileTimelineItem : AbsBaseMessageItem R.drawable.ic_shield_trusted From 6f2d7aebbab91b469493874ab6b23729a3bd675b Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 8 Apr 2020 16:37:52 +0200 Subject: [PATCH 09/20] code review --- .../detail/timeline/factory/MergedHeaderItemFactory.kt | 8 ++++---- ...{MergedHeaderItem.kt => MergedMembershipEventsItem.kt} | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/{MergedHeaderItem.kt => MergedMembershipEventsItem.kt} (96%) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt index 00e90558a6..377fc5ab4a 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt @@ -30,8 +30,8 @@ import im.vector.riotx.features.home.room.detail.timeline.helper.canBeMerged import im.vector.riotx.features.home.room.detail.timeline.helper.isRoomConfiguration import im.vector.riotx.features.home.room.detail.timeline.helper.prevSameTypeEvents import im.vector.riotx.features.home.room.detail.timeline.item.BasedMergedItem -import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem -import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem_ +import im.vector.riotx.features.home.room.detail.timeline.item.MergedMembershipEventsItem +import im.vector.riotx.features.home.room.detail.timeline.item.MergedMembershipEventsItem_ import im.vector.riotx.features.home.room.detail.timeline.item.MergedRoomCreationItem import im.vector.riotx.features.home.room.detail.timeline.item.MergedRoomCreationItem_ import javax.inject.Inject @@ -94,7 +94,7 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act collapsedEventIds.removeAll(mergedEventIds) } val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() } - val attributes = MergedHeaderItem.Attributes( + val attributes = MergedMembershipEventsItem.Attributes( isCollapsed = isCollapsed, mergeData = mergedData, avatarRenderer = avatarRenderer, @@ -104,7 +104,7 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act }, readReceiptsCallback = callback ) - MergedHeaderItem_() + MergedMembershipEventsItem_() .id(mergeId) .leftGuideline(avatarSizeProvider.leftGuideline) .highlighted(isCollapsed && highlighted) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedMembershipEventsItem.kt similarity index 96% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt rename to vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedMembershipEventsItem.kt index 59f4d08d68..8e3ba0bcff 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedMembershipEventsItem.kt @@ -29,7 +29,7 @@ import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController @EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo) -abstract class MergedHeaderItem : BasedMergedItem() { +abstract class MergedMembershipEventsItem : BasedMergedItem() { override fun getViewType() = STUB_ID From 34dec64d9cd2d6fb8c34e596385d00a5b0484270 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 8 Apr 2020 17:55:47 +0200 Subject: [PATCH 10/20] Fixes #1214 --- CHANGES.md | 1 + .../quads/SharedSecureStorageViewModel.kt | 15 ++- .../verification/VerificationBottomSheet.kt | 3 +- .../VerificationBottomSheetViewModel.kt | 109 +++++++++++++----- 4 files changed, 92 insertions(+), 36 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 983c9841cd..174f4e3a6f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ Improvements 🙌: - Cross-Signing | Setup key backup as part of SSSS bootstrapping (#1201) - Cross-Signing | Gossip key backup recovery key (#1200) - Show room encryption status as a bubble tile (#1078) + - Cross-Signing | Restore history after recover from passphrase (#1214) Bugfix 🐛: - Missing avatar/displayname after verification request message (#841) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/riotx/features/crypto/quads/SharedSecureStorageViewModel.kt index a9f5d33888..3eef4b20cf 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/quads/SharedSecureStorageViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/quads/SharedSecureStorageViewModel.kt @@ -37,6 +37,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import timber.log.Timber import java.io.ByteArrayOutputStream data class SharedSecureStorageViewState( @@ -117,11 +118,15 @@ class SharedSecureStorageViewModel @AssistedInject constructor( withContext(Dispatchers.IO) { args.requestedSecrets.forEach { val res = awaitCallback { callback -> - session.sharedSecretStorageService.getSecret( - name = it, - keyId = keyInfo.id, - secretKey = keySpec, - callback = callback) + if (session.getAccountDataEvent(it) != null) { + session.sharedSecretStorageService.getSecret( + name = it, + keyId = keyInfo.id, + secretKey = keySpec, + callback = callback) + } else { + Timber.w("## Cannot find secret $it in SSSS, skip") + } } decryptedSecretMap[it] = res } diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheet.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheet.kt index cd91cc3712..6b75c0147a 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheet.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheet.kt @@ -32,6 +32,7 @@ import com.airbnb.mvrx.MvRx import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import im.vector.matrix.android.api.session.Session +import im.vector.matrix.android.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import im.vector.matrix.android.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import im.vector.matrix.android.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import im.vector.matrix.android.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME @@ -108,7 +109,7 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() { startActivityForResult(SharedSecureStorageActivity.newIntent( requireContext(), null, // use default key - listOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME), + listOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME), SharedSecureStorageActivity.DEFAULT_RESULT_KEYSTORE_ALIAS ), SECRET_REQUEST_CODE) } diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt index c37bba1469..71a9ec73e7 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt @@ -15,6 +15,7 @@ */ package im.vector.riotx.features.crypto.verification +import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.Async import com.airbnb.mvrx.Fail import com.airbnb.mvrx.FragmentViewModelContext @@ -28,6 +29,7 @@ import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.Session +import im.vector.matrix.android.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import im.vector.matrix.android.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import im.vector.matrix.android.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import im.vector.matrix.android.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME @@ -46,8 +48,13 @@ import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.api.util.toMatrixItem import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64 import im.vector.matrix.android.internal.crypto.crosssigning.isVerified +import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersionResult +import im.vector.matrix.android.internal.crypto.keysbackup.util.computeRecoveryKey +import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult +import im.vector.matrix.android.internal.util.awaitCallback import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.platform.VectorViewModel +import kotlinx.coroutines.launch import timber.log.Timber data class VerificationBottomSheetViewState( @@ -334,40 +341,82 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( _viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore) } is VerificationAction.GotResultFromSsss -> { - try { - action.cypherData.fromBase64().inputStream().use { ins -> - val res = session.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 - session.sessionParams.credentials.deviceId?.let { deviceId -> - session.cryptoService() - .crossSigningService().trustDevice(deviceId, object : MatrixCallback { - override fun onFailure(failure: Throwable) { - Timber.w(failure, "Failed to sign my device after recovery") - } - }) - } - - setState { - copy(verifiedFromPrivateKeys = true) - } - } else { - // POP UP something - _viewEvents.post(VerificationBottomSheetViewEvents.ModalError("Failed to import keys")) - } - } - } catch (failure: Throwable) { - _viewEvents.post(VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage)) - } + handleSecretBackFromSSSS(action) } }.exhaustive } + private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) { + try { + action.cypherData.fromBase64().inputStream().use { ins -> + val res = session.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 + session.sessionParams.credentials.deviceId?.let { deviceId -> + session.cryptoService() + .crossSigningService().trustDevice(deviceId, object : MatrixCallback { + override fun onFailure(failure: Throwable) { + Timber.w(failure, "Failed to sign my device after recovery") + } + }) + } + + setState { + copy(verifiedFromPrivateKeys = true) + } + + // try to get keybackup key + } else { + // POP UP something + _viewEvents.post(VerificationBottomSheetViewEvents.ModalError("Failed to import keys")) + } + + // try the keybackup + tentativeRestoreBackup(res) + Unit + } + } catch (failure: Throwable) { + _viewEvents.post(VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage)) + } + } + + private fun tentativeRestoreBackup(res: Map?) { + viewModelScope.launch { + try { + val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also { + Timber.v("## Keybackup secret not restored from SSSS") + } + + val version = awaitCallback { + session.cryptoService().keysBackupService().getCurrentVersion(it) + } ?: return@launch + + awaitCallback { + session.cryptoService().keysBackupService().restoreKeysWithRecoveryKey( + version, + computeRecoveryKey(secret.fromBase64()), + null, + null, + null, + it + ) + } + + awaitCallback { + session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true, it) + } + } catch (failure: Throwable) { + // Just ignore for now + Timber.v("## Failed to restore backup after SSSS recovery") + } + } + } + override fun transactionCreated(tx: VerificationTransaction) { transactionUpdated(tx) } From 7c0137e2dc8e42e0690b0ce2ae144d5b7f7faa60 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 9 Apr 2020 10:46:52 +0200 Subject: [PATCH 11/20] Fix / await callback suspend forever --- .../crypto/quads/SharedSecureStorageViewModel.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/riotx/features/crypto/quads/SharedSecureStorageViewModel.kt index 3eef4b20cf..9cd60eba43 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/quads/SharedSecureStorageViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/quads/SharedSecureStorageViewModel.kt @@ -16,6 +16,7 @@ package im.vector.riotx.features.crypto.quads +import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.MvRx import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory @@ -34,7 +35,6 @@ import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.platform.WaitingViewData import im.vector.riotx.core.resources.StringProvider import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber @@ -78,7 +78,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( private fun handleSubmitPassphrase(action: SharedSecureStorageAction.SubmitPassphrase) { val decryptedSecretMap = HashMap() - GlobalScope.launch(Dispatchers.IO) { + viewModelScope.launch(Dispatchers.IO) { runCatching { _viewEvents.post(SharedSecureStorageViewEvent.ShowModalLoading) val passphrase = action.passphrase @@ -117,18 +117,18 @@ class SharedSecureStorageViewModel @AssistedInject constructor( withContext(Dispatchers.IO) { args.requestedSecrets.forEach { - val res = awaitCallback { callback -> - if (session.getAccountDataEvent(it) != null) { + if (session.getAccountDataEvent(it) != null) { + val res = awaitCallback { callback -> session.sharedSecretStorageService.getSecret( name = it, keyId = keyInfo.id, secretKey = keySpec, callback = callback) - } else { - Timber.w("## Cannot find secret $it in SSSS, skip") } + decryptedSecretMap[it] = res + } else { + Timber.w("## Cannot find secret $it in SSSS, skip") } - decryptedSecretMap[it] = res } } }.fold({ From a703574004950c351766af6d4f7981a7d4540219 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 10 Apr 2020 10:57:09 +0200 Subject: [PATCH 12/20] Uniform emoji representation for all platform --- CHANGES.md | 1 + .../verification/EmojiRepresentation.kt | 5 +- .../SASDefaultVerificationTransaction.kt | 11 +- .../crypto/verification/VerificationEmoji.kt | 128 +++++++++--------- .../src/main/res/drawable/ic_airplane.xml | 18 +++ .../src/main/res/drawable/ic_anchor.xml | 12 ++ .../src/main/res/drawable/ic_apple.xml | 15 ++ .../src/main/res/drawable/ic_ball.xml | 15 ++ .../src/main/res/drawable/ic_banana.xml | 36 +++++ .../src/main/res/drawable/ic_bell.xml | 15 ++ .../src/main/res/drawable/ic_bicycle.xml | 27 ++++ .../src/main/res/drawable/ic_book.xml | 24 ++++ .../src/main/res/drawable/ic_butterfly.xml | 39 ++++++ .../src/main/res/drawable/ic_cactus.xml | 51 +++++++ .../src/main/res/drawable/ic_cake.xml | 42 ++++++ .../src/main/res/drawable/ic_cat.xml | 36 +++++ .../src/main/res/drawable/ic_clock.xml | 27 ++++ .../src/main/res/drawable/ic_cloud.xml | 12 ++ .../src/main/res/drawable/ic_corn.xml | 18 +++ .../src/main/res/drawable/ic_dog.xml | 45 ++++++ .../src/main/res/drawable/ic_elephant.xml | 15 ++ .../src/main/res/drawable/ic_fire.xml | 12 ++ .../src/main/res/drawable/ic_fish.xml | 24 ++++ .../src/main/res/drawable/ic_flag.xml | 24 ++++ .../src/main/res/drawable/ic_flower.xml | 15 ++ .../src/main/res/drawable/ic_folder.xml | 12 ++ .../src/main/res/drawable/ic_gift.xml | 21 +++ .../src/main/res/drawable/ic_glasses.xml | 12 ++ .../src/main/res/drawable/ic_globe.xml | 15 ++ .../src/main/res/drawable/ic_guitar.xml | 51 +++++++ .../src/main/res/drawable/ic_hammer.xml | 12 ++ .../src/main/res/drawable/ic_hat.xml | 15 ++ .../src/main/res/drawable/ic_headphone.xml | 15 ++ .../src/main/res/drawable/ic_heart.xml | 9 ++ .../src/main/res/drawable/ic_horse.xml | 33 +++++ .../src/main/res/drawable/ic_hourglass.xml | 15 ++ .../src/main/res/drawable/ic_key.xml | 9 ++ .../src/main/res/drawable/ic_light_bulb.xml | 21 +++ .../src/main/res/drawable/ic_lion.xml | 54 ++++++++ .../src/main/res/drawable/ic_lock.xml | 12 ++ .../src/main/res/drawable/ic_moon.xml | 12 ++ .../src/main/res/drawable/ic_mushroom.xml | 24 ++++ .../src/main/res/drawable/ic_octopus.xml | 24 ++++ .../src/main/res/drawable/ic_panda.xml | 42 ++++++ .../src/main/res/drawable/ic_paperclip.xml | 9 ++ .../src/main/res/drawable/ic_pencil.xml | 24 ++++ .../src/main/res/drawable/ic_penguin.xml | 21 +++ .../src/main/res/drawable/ic_phone.xml | 15 ++ .../src/main/res/drawable/ic_pig.xml | 21 +++ .../src/main/res/drawable/ic_pin.xml | 18 +++ .../src/main/res/drawable/ic_pizza.xml | 21 +++ .../src/main/res/drawable/ic_rabbit.xml | 27 ++++ .../src/main/res/drawable/ic_robot.xml | 48 +++++++ .../src/main/res/drawable/ic_rocket.xml | 24 ++++ .../src/main/res/drawable/ic_rooster.xml | 18 +++ .../src/main/res/drawable/ic_santa.xml | 42 ++++++ .../src/main/res/drawable/ic_scissors.xml | 21 +++ .../src/main/res/drawable/ic_smiley.xml | 21 +++ .../src/main/res/drawable/ic_strawberry.xml | 15 ++ .../src/main/res/drawable/ic_thumbs_up.xml | 12 ++ .../src/main/res/drawable/ic_train.xml | 72 ++++++++++ .../src/main/res/drawable/ic_tree.xml | 54 ++++++++ .../src/main/res/drawable/ic_trophy.xml | 18 +++ .../src/main/res/drawable/ic_trumpet.xml | 21 +++ .../src/main/res/drawable/ic_turtle.xml | 21 +++ .../src/main/res/drawable/ic_umbrella.xml | 18 +++ .../src/main/res/drawable/ic_unicorn.xml | 30 ++++ .../src/main/res/drawable/ic_wrench.xml | 9 ++ .../riotx/features/debug/sas/SasEmojiItem.kt | 10 +- .../src/main/assets/open_source_licenses.html | 9 ++ .../BottomSheetVerificationEmojisItem.kt | 53 +++++--- .../src/main/res/layout/item_emoji_verif.xml | 13 ++ 72 files changed, 1668 insertions(+), 92 deletions(-) create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_airplane.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_anchor.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_apple.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_ball.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_banana.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_bell.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_bicycle.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_book.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_butterfly.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_cactus.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_cake.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_cat.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_clock.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_cloud.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_corn.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_dog.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_elephant.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_fire.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_fish.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_flag.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_flower.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_folder.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_gift.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_glasses.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_globe.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_guitar.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_hammer.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_hat.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_headphone.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_heart.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_horse.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_hourglass.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_key.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_light_bulb.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_lion.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_lock.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_moon.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_mushroom.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_octopus.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_panda.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_paperclip.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_pencil.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_penguin.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_phone.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_pig.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_pin.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_pizza.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_rabbit.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_robot.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_rocket.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_rooster.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_santa.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_scissors.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_smiley.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_strawberry.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_thumbs_up.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_train.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_tree.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_trophy.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_trumpet.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_turtle.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_umbrella.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_unicorn.xml create mode 100644 matrix-sdk-android/src/main/res/drawable/ic_wrench.xml diff --git a/CHANGES.md b/CHANGES.md index 983c9841cd..0bf3dc0a5d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ Improvements 🙌: - Cross-Signing | Setup key backup as part of SSSS bootstrapping (#1201) - Cross-Signing | Gossip key backup recovery key (#1200) - Show room encryption status as a bubble tile (#1078) + - Emoji Verification | It's not the same butterfly! (#1220) Bugfix 🐛: - Missing avatar/displayname after verification request message (#841) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/verification/EmojiRepresentation.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/verification/EmojiRepresentation.kt index 9ee7c92788..7d18d9bd70 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/verification/EmojiRepresentation.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/verification/EmojiRepresentation.kt @@ -16,7 +16,10 @@ package im.vector.matrix.android.api.session.crypto.verification +import androidx.annotation.DrawableRes import androidx.annotation.StringRes data class EmojiRepresentation(val emoji: String, - @StringRes val nameResId: Int) + @StringRes val nameResId: Int, + @DrawableRes val drawableRes: Int? = null +) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASDefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASDefaultVerificationTransaction.kt index a878ad06eb..2a502730fa 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASDefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASDefaultVerificationTransaction.kt @@ -15,7 +15,6 @@ */ package im.vector.matrix.android.internal.crypto.verification -import android.os.Build import im.vector.matrix.android.api.extensions.orFalse import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService import im.vector.matrix.android.api.session.crypto.verification.CancelCode @@ -74,13 +73,9 @@ internal abstract class SASDefaultVerificationTransaction( // ordered by preferred order val KNOWN_MACS = listOf(SAS_MAC_SHA256, SAS_MAC_SHA256_LONGKDF) - // older devices have limited support of emoji, so reply with decimal - val KNOWN_SHORT_CODES = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - listOf(SasMode.EMOJI, SasMode.DECIMAL) - } else { - listOf(SasMode.DECIMAL) - } + // older devices have limited support of emoji but SDK offers images for the 64 verification emojis + // so always send that we support EMOJI + val KNOWN_SHORT_CODES = listOf(SasMode.EMOJI, SasMode.DECIMAL) } override var state: VerificationTxState = VerificationTxState.None diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt index eb9acd045a..738b56dc5b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt @@ -20,69 +20,69 @@ import im.vector.matrix.android.api.session.crypto.verification.EmojiRepresentat internal fun getEmojiForCode(code: Int): EmojiRepresentation { return when (code % 64) { - 0 -> EmojiRepresentation("🐶", R.string.verification_emoji_dog) - 1 -> EmojiRepresentation("🐱", R.string.verification_emoji_cat) - 2 -> EmojiRepresentation("🦁", R.string.verification_emoji_lion) - 3 -> EmojiRepresentation("🐎", R.string.verification_emoji_horse) - 4 -> EmojiRepresentation("🦄", R.string.verification_emoji_unicorn) - 5 -> EmojiRepresentation("🐷", R.string.verification_emoji_pig) - 6 -> EmojiRepresentation("🐘", R.string.verification_emoji_elephant) - 7 -> EmojiRepresentation("🐰", R.string.verification_emoji_rabbit) - 8 -> EmojiRepresentation("🐼", R.string.verification_emoji_panda) - 9 -> EmojiRepresentation("🐓", R.string.verification_emoji_rooster) - 10 -> EmojiRepresentation("🐧", R.string.verification_emoji_penguin) - 11 -> EmojiRepresentation("🐢", R.string.verification_emoji_turtle) - 12 -> EmojiRepresentation("🐟", R.string.verification_emoji_fish) - 13 -> EmojiRepresentation("🐙", R.string.verification_emoji_octopus) - 14 -> EmojiRepresentation("🦋", R.string.verification_emoji_butterfly) - 15 -> EmojiRepresentation("🌷", R.string.verification_emoji_flower) - 16 -> EmojiRepresentation("🌳", R.string.verification_emoji_tree) - 17 -> EmojiRepresentation("🌵", R.string.verification_emoji_cactus) - 18 -> EmojiRepresentation("🍄", R.string.verification_emoji_mushroom) - 19 -> EmojiRepresentation("🌏", R.string.verification_emoji_globe) - 20 -> EmojiRepresentation("🌙", R.string.verification_emoji_moon) - 21 -> EmojiRepresentation("☁️", R.string.verification_emoji_cloud) - 22 -> EmojiRepresentation("🔥", R.string.verification_emoji_fire) - 23 -> EmojiRepresentation("🍌", R.string.verification_emoji_banana) - 24 -> EmojiRepresentation("🍎", R.string.verification_emoji_apple) - 25 -> EmojiRepresentation("🍓", R.string.verification_emoji_strawberry) - 26 -> EmojiRepresentation("🌽", R.string.verification_emoji_corn) - 27 -> EmojiRepresentation("🍕", R.string.verification_emoji_pizza) - 28 -> EmojiRepresentation("🎂", R.string.verification_emoji_cake) - 29 -> EmojiRepresentation("❤️", R.string.verification_emoji_heart) - 30 -> EmojiRepresentation("😀", R.string.verification_emoji_smiley) - 31 -> EmojiRepresentation("🤖", R.string.verification_emoji_robot) - 32 -> EmojiRepresentation("🎩", R.string.verification_emoji_hat) - 33 -> EmojiRepresentation("👓", R.string.verification_emoji_glasses) - 34 -> EmojiRepresentation("🔧", R.string.verification_emoji_wrench) - 35 -> EmojiRepresentation("🎅", R.string.verification_emoji_santa) - 36 -> EmojiRepresentation("👍", R.string.verification_emoji_thumbsup) - 37 -> EmojiRepresentation("☂️", R.string.verification_emoji_umbrella) - 38 -> EmojiRepresentation("⌛", R.string.verification_emoji_hourglass) - 39 -> EmojiRepresentation("⏰", R.string.verification_emoji_clock) - 40 -> EmojiRepresentation("🎁", R.string.verification_emoji_gift) - 41 -> EmojiRepresentation("💡", R.string.verification_emoji_lightbulb) - 42 -> EmojiRepresentation("📕", R.string.verification_emoji_book) - 43 -> EmojiRepresentation("✏️", R.string.verification_emoji_pencil) - 44 -> EmojiRepresentation("📎", R.string.verification_emoji_paperclip) - 45 -> EmojiRepresentation("✂️", R.string.verification_emoji_scissors) - 46 -> EmojiRepresentation("🔒", R.string.verification_emoji_lock) - 47 -> EmojiRepresentation("🔑", R.string.verification_emoji_key) - 48 -> EmojiRepresentation("🔨", R.string.verification_emoji_hammer) - 49 -> EmojiRepresentation("☎️", R.string.verification_emoji_telephone) - 50 -> EmojiRepresentation("🏁", R.string.verification_emoji_flag) - 51 -> EmojiRepresentation("🚂", R.string.verification_emoji_train) - 52 -> EmojiRepresentation("🚲", R.string.verification_emoji_bicycle) - 53 -> EmojiRepresentation("✈️", R.string.verification_emoji_airplane) - 54 -> EmojiRepresentation("🚀", R.string.verification_emoji_rocket) - 55 -> EmojiRepresentation("🏆", R.string.verification_emoji_trophy) - 56 -> EmojiRepresentation("⚽", R.string.verification_emoji_ball) - 57 -> EmojiRepresentation("🎸", R.string.verification_emoji_guitar) - 58 -> EmojiRepresentation("🎺", R.string.verification_emoji_trumpet) - 59 -> EmojiRepresentation("🔔", R.string.verification_emoji_bell) - 60 -> EmojiRepresentation("⚓", R.string.verification_emoji_anchor) - 61 -> EmojiRepresentation("🎧", R.string.verification_emoji_headphone) - 62 -> EmojiRepresentation("📁", R.string.verification_emoji_folder) - /* 63 */ else -> EmojiRepresentation("📌", R.string.verification_emoji_pin) + 0 -> EmojiRepresentation("🐶", R.string.verification_emoji_dog, R.drawable.ic_dog) + 1 -> EmojiRepresentation("🐱", R.string.verification_emoji_cat, R.drawable.ic_cat) + 2 -> EmojiRepresentation("🦁", R.string.verification_emoji_lion, R.drawable.ic_lion) + 3 -> EmojiRepresentation("🐎", R.string.verification_emoji_horse, R.drawable.ic_horse) + 4 -> EmojiRepresentation("🦄", R.string.verification_emoji_unicorn, R.drawable.ic_unicorn) + 5 -> EmojiRepresentation("🐷", R.string.verification_emoji_pig, R.drawable.ic_pig) + 6 -> EmojiRepresentation("🐘", R.string.verification_emoji_elephant, R.drawable.ic_elephant) + 7 -> EmojiRepresentation("🐰", R.string.verification_emoji_rabbit, R.drawable.ic_rabbit) + 8 -> EmojiRepresentation("🐼", R.string.verification_emoji_panda, R.drawable.ic_panda) + 9 -> EmojiRepresentation("🐓", R.string.verification_emoji_rooster, R.drawable.ic_rooster) + 10 -> EmojiRepresentation("🐧", R.string.verification_emoji_penguin, R.drawable.ic_penguin) + 11 -> EmojiRepresentation("🐢", R.string.verification_emoji_turtle, R.drawable.ic_turtle) + 12 -> EmojiRepresentation("🐟", R.string.verification_emoji_fish, R.drawable.ic_fish) + 13 -> EmojiRepresentation("🐙", R.string.verification_emoji_octopus, R.drawable.ic_octopus) + 14 -> EmojiRepresentation("🦋", R.string.verification_emoji_butterfly, R.drawable.ic_butterfly) + 15 -> EmojiRepresentation("🌷", R.string.verification_emoji_flower, R.drawable.ic_flower) + 16 -> EmojiRepresentation("🌳", R.string.verification_emoji_tree, R.drawable.ic_tree) + 17 -> EmojiRepresentation("🌵", R.string.verification_emoji_cactus, R.drawable.ic_cactus) + 18 -> EmojiRepresentation("🍄", R.string.verification_emoji_mushroom, R.drawable.ic_mushroom) + 19 -> EmojiRepresentation("🌏", R.string.verification_emoji_globe, R.drawable.ic_globe) + 20 -> EmojiRepresentation("🌙", R.string.verification_emoji_moon, R.drawable.ic_moon) + 21 -> EmojiRepresentation("☁️", R.string.verification_emoji_cloud, R.drawable.ic_cloud) + 22 -> EmojiRepresentation("🔥", R.string.verification_emoji_fire, R.drawable.ic_fire) + 23 -> EmojiRepresentation("🍌", R.string.verification_emoji_banana, R.drawable.ic_banana) + 24 -> EmojiRepresentation("🍎", R.string.verification_emoji_apple, R.drawable.ic_apple) + 25 -> EmojiRepresentation("🍓", R.string.verification_emoji_strawberry, R.drawable.ic_strawberry) + 26 -> EmojiRepresentation("🌽", R.string.verification_emoji_corn, R.drawable.ic_corn) + 27 -> EmojiRepresentation("🍕", R.string.verification_emoji_pizza, R.drawable.ic_pizza) + 28 -> EmojiRepresentation("🎂", R.string.verification_emoji_cake, R.drawable.ic_cake) + 29 -> EmojiRepresentation("❤️", R.string.verification_emoji_heart, R.drawable.ic_heart) + 30 -> EmojiRepresentation("😀", R.string.verification_emoji_smiley, R.drawable.ic_smiley) + 31 -> EmojiRepresentation("🤖", R.string.verification_emoji_robot, R.drawable.ic_robot) + 32 -> EmojiRepresentation("🎩", R.string.verification_emoji_hat, R.drawable.ic_hat) + 33 -> EmojiRepresentation("👓", R.string.verification_emoji_glasses, R.drawable.ic_glasses) + 34 -> EmojiRepresentation("🔧", R.string.verification_emoji_wrench, R.drawable.ic_wrench) + 35 -> EmojiRepresentation("🎅", R.string.verification_emoji_santa, R.drawable.ic_santa) + 36 -> EmojiRepresentation("👍", R.string.verification_emoji_thumbsup, R.drawable.ic_thumbs_up) + 37 -> EmojiRepresentation("☂️", R.string.verification_emoji_umbrella, R.drawable.ic_umbrella) + 38 -> EmojiRepresentation("⌛", R.string.verification_emoji_hourglass, R.drawable.ic_hourglass) + 39 -> EmojiRepresentation("⏰", R.string.verification_emoji_clock, R.drawable.ic_clock) + 40 -> EmojiRepresentation("🎁", R.string.verification_emoji_gift, R.drawable.ic_gift) + 41 -> EmojiRepresentation("💡", R.string.verification_emoji_lightbulb, R.drawable.ic_light_bulb) + 42 -> EmojiRepresentation("📕", R.string.verification_emoji_book, R.drawable.ic_book) + 43 -> EmojiRepresentation("✏️", R.string.verification_emoji_pencil, R.drawable.ic_pencil) + 44 -> EmojiRepresentation("📎", R.string.verification_emoji_paperclip, R.drawable.ic_paperclip) + 45 -> EmojiRepresentation("✂️", R.string.verification_emoji_scissors, R.drawable.ic_scissors) + 46 -> EmojiRepresentation("🔒", R.string.verification_emoji_lock, R.drawable.ic_lock) + 47 -> EmojiRepresentation("🔑", R.string.verification_emoji_key, R.drawable.ic_key) + 48 -> EmojiRepresentation("🔨", R.string.verification_emoji_hammer, R.drawable.ic_hammer) + 49 -> EmojiRepresentation("☎️", R.string.verification_emoji_telephone, R.drawable.ic_phone) + 50 -> EmojiRepresentation("🏁", R.string.verification_emoji_flag, R.drawable.ic_flag) + 51 -> EmojiRepresentation("🚂", R.string.verification_emoji_train, R.drawable.ic_train) + 52 -> EmojiRepresentation("🚲", R.string.verification_emoji_bicycle, R.drawable.ic_bicycle) + 53 -> EmojiRepresentation("✈️", R.string.verification_emoji_airplane, R.drawable.ic_airplane) + 54 -> EmojiRepresentation("🚀", R.string.verification_emoji_rocket, R.drawable.ic_rocket) + 55 -> EmojiRepresentation("🏆", R.string.verification_emoji_trophy, R.drawable.ic_trophy) + 56 -> EmojiRepresentation("⚽", R.string.verification_emoji_ball, R.drawable.ic_ball) + 57 -> EmojiRepresentation("🎸", R.string.verification_emoji_guitar, R.drawable.ic_guitar) + 58 -> EmojiRepresentation("🎺", R.string.verification_emoji_trumpet, R.drawable.ic_trumpet) + 59 -> EmojiRepresentation("🔔", R.string.verification_emoji_bell, R.drawable.ic_bell) + 60 -> EmojiRepresentation("⚓", R.string.verification_emoji_anchor, R.drawable.ic_anchor) + 61 -> EmojiRepresentation("🎧", R.string.verification_emoji_headphone, R.drawable.ic_headphone) + 62 -> EmojiRepresentation("📁", R.string.verification_emoji_folder, R.drawable.ic_folder) + /* 63 */ else -> EmojiRepresentation("📌", R.string.verification_emoji_pin, R.drawable.ic_pin) } } diff --git a/matrix-sdk-android/src/main/res/drawable/ic_airplane.xml b/matrix-sdk-android/src/main/res/drawable/ic_airplane.xml new file mode 100644 index 0000000000..72026cd7a0 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_airplane.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_anchor.xml b/matrix-sdk-android/src/main/res/drawable/ic_anchor.xml new file mode 100644 index 0000000000..b89d033b9e --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_anchor.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_apple.xml b/matrix-sdk-android/src/main/res/drawable/ic_apple.xml new file mode 100644 index 0000000000..54e0f9a3c0 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_apple.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_ball.xml b/matrix-sdk-android/src/main/res/drawable/ic_ball.xml new file mode 100644 index 0000000000..b12c6d245b --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_ball.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_banana.xml b/matrix-sdk-android/src/main/res/drawable/ic_banana.xml new file mode 100644 index 0000000000..cdd3cb1b9f --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_banana.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_bell.xml b/matrix-sdk-android/src/main/res/drawable/ic_bell.xml new file mode 100644 index 0000000000..2f29828bcf --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_bell.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_bicycle.xml b/matrix-sdk-android/src/main/res/drawable/ic_bicycle.xml new file mode 100644 index 0000000000..1427e793c5 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_bicycle.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_book.xml b/matrix-sdk-android/src/main/res/drawable/ic_book.xml new file mode 100644 index 0000000000..8e3ecc00c0 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_book.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_butterfly.xml b/matrix-sdk-android/src/main/res/drawable/ic_butterfly.xml new file mode 100644 index 0000000000..d4b557a7ed --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_butterfly.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_cactus.xml b/matrix-sdk-android/src/main/res/drawable/ic_cactus.xml new file mode 100644 index 0000000000..ce8aff0657 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_cactus.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_cake.xml b/matrix-sdk-android/src/main/res/drawable/ic_cake.xml new file mode 100644 index 0000000000..9ebb3c0904 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_cake.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_cat.xml b/matrix-sdk-android/src/main/res/drawable/ic_cat.xml new file mode 100644 index 0000000000..b34cf63d98 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_cat.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_clock.xml b/matrix-sdk-android/src/main/res/drawable/ic_clock.xml new file mode 100644 index 0000000000..48d7150c36 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_clock.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_cloud.xml b/matrix-sdk-android/src/main/res/drawable/ic_cloud.xml new file mode 100644 index 0000000000..d390bd6e87 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_cloud.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_corn.xml b/matrix-sdk-android/src/main/res/drawable/ic_corn.xml new file mode 100644 index 0000000000..d863d03c2a --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_corn.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_dog.xml b/matrix-sdk-android/src/main/res/drawable/ic_dog.xml new file mode 100644 index 0000000000..8346a5ebee --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_dog.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_elephant.xml b/matrix-sdk-android/src/main/res/drawable/ic_elephant.xml new file mode 100644 index 0000000000..d0a2de42cb --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_elephant.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_fire.xml b/matrix-sdk-android/src/main/res/drawable/ic_fire.xml new file mode 100644 index 0000000000..ebf42039b1 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_fire.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_fish.xml b/matrix-sdk-android/src/main/res/drawable/ic_fish.xml new file mode 100644 index 0000000000..30907f2496 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_fish.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_flag.xml b/matrix-sdk-android/src/main/res/drawable/ic_flag.xml new file mode 100644 index 0000000000..250388dc4a --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_flag.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_flower.xml b/matrix-sdk-android/src/main/res/drawable/ic_flower.xml new file mode 100644 index 0000000000..8a91221a80 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_flower.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_folder.xml b/matrix-sdk-android/src/main/res/drawable/ic_folder.xml new file mode 100644 index 0000000000..9320766492 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_folder.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_gift.xml b/matrix-sdk-android/src/main/res/drawable/ic_gift.xml new file mode 100644 index 0000000000..d18c6e860a --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_gift.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_glasses.xml b/matrix-sdk-android/src/main/res/drawable/ic_glasses.xml new file mode 100644 index 0000000000..8913d1ffd7 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_glasses.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_globe.xml b/matrix-sdk-android/src/main/res/drawable/ic_globe.xml new file mode 100644 index 0000000000..2a07829cb3 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_globe.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_guitar.xml b/matrix-sdk-android/src/main/res/drawable/ic_guitar.xml new file mode 100644 index 0000000000..2622fbe416 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_guitar.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_hammer.xml b/matrix-sdk-android/src/main/res/drawable/ic_hammer.xml new file mode 100644 index 0000000000..7b70654d52 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_hammer.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_hat.xml b/matrix-sdk-android/src/main/res/drawable/ic_hat.xml new file mode 100644 index 0000000000..15f980bdb1 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_hat.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_headphone.xml b/matrix-sdk-android/src/main/res/drawable/ic_headphone.xml new file mode 100644 index 0000000000..cbc43e7601 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_headphone.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_heart.xml b/matrix-sdk-android/src/main/res/drawable/ic_heart.xml new file mode 100644 index 0000000000..d37bcc33d1 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_heart.xml @@ -0,0 +1,9 @@ + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_horse.xml b/matrix-sdk-android/src/main/res/drawable/ic_horse.xml new file mode 100644 index 0000000000..bedf0f6f46 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_horse.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_hourglass.xml b/matrix-sdk-android/src/main/res/drawable/ic_hourglass.xml new file mode 100644 index 0000000000..8bb37a35bb --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_hourglass.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_key.xml b/matrix-sdk-android/src/main/res/drawable/ic_key.xml new file mode 100644 index 0000000000..4cd1d033f7 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_key.xml @@ -0,0 +1,9 @@ + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_light_bulb.xml b/matrix-sdk-android/src/main/res/drawable/ic_light_bulb.xml new file mode 100644 index 0000000000..18f3149500 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_light_bulb.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_lion.xml b/matrix-sdk-android/src/main/res/drawable/ic_lion.xml new file mode 100644 index 0000000000..b97a508fc2 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_lion.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_lock.xml b/matrix-sdk-android/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000000..de3979434f --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_moon.xml b/matrix-sdk-android/src/main/res/drawable/ic_moon.xml new file mode 100644 index 0000000000..3f5abe6ae3 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_moon.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_mushroom.xml b/matrix-sdk-android/src/main/res/drawable/ic_mushroom.xml new file mode 100644 index 0000000000..72f7036856 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_mushroom.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_octopus.xml b/matrix-sdk-android/src/main/res/drawable/ic_octopus.xml new file mode 100644 index 0000000000..054760f3b8 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_octopus.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_panda.xml b/matrix-sdk-android/src/main/res/drawable/ic_panda.xml new file mode 100644 index 0000000000..ab1e718c44 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_panda.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_paperclip.xml b/matrix-sdk-android/src/main/res/drawable/ic_paperclip.xml new file mode 100644 index 0000000000..e8f89859d6 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_paperclip.xml @@ -0,0 +1,9 @@ + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_pencil.xml b/matrix-sdk-android/src/main/res/drawable/ic_pencil.xml new file mode 100644 index 0000000000..3b9f51fca5 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_pencil.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_penguin.xml b/matrix-sdk-android/src/main/res/drawable/ic_penguin.xml new file mode 100644 index 0000000000..fb2e05760f --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_penguin.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_phone.xml b/matrix-sdk-android/src/main/res/drawable/ic_phone.xml new file mode 100644 index 0000000000..7beda09c4e --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_phone.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_pig.xml b/matrix-sdk-android/src/main/res/drawable/ic_pig.xml new file mode 100644 index 0000000000..c31bd06c52 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_pig.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_pin.xml b/matrix-sdk-android/src/main/res/drawable/ic_pin.xml new file mode 100644 index 0000000000..f10e4606a9 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_pin.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_pizza.xml b/matrix-sdk-android/src/main/res/drawable/ic_pizza.xml new file mode 100644 index 0000000000..a514aeb3d6 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_pizza.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_rabbit.xml b/matrix-sdk-android/src/main/res/drawable/ic_rabbit.xml new file mode 100644 index 0000000000..c8ff75c999 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_rabbit.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_robot.xml b/matrix-sdk-android/src/main/res/drawable/ic_robot.xml new file mode 100644 index 0000000000..a53cfe99c0 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_robot.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_rocket.xml b/matrix-sdk-android/src/main/res/drawable/ic_rocket.xml new file mode 100644 index 0000000000..4097ed9030 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_rocket.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_rooster.xml b/matrix-sdk-android/src/main/res/drawable/ic_rooster.xml new file mode 100644 index 0000000000..cb7ad563f0 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_rooster.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_santa.xml b/matrix-sdk-android/src/main/res/drawable/ic_santa.xml new file mode 100644 index 0000000000..4f7bc1a24f --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_santa.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_scissors.xml b/matrix-sdk-android/src/main/res/drawable/ic_scissors.xml new file mode 100644 index 0000000000..98e68c2071 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_scissors.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_smiley.xml b/matrix-sdk-android/src/main/res/drawable/ic_smiley.xml new file mode 100644 index 0000000000..28c2394b99 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_smiley.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_strawberry.xml b/matrix-sdk-android/src/main/res/drawable/ic_strawberry.xml new file mode 100644 index 0000000000..0eeb290d9d --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_strawberry.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_thumbs_up.xml b/matrix-sdk-android/src/main/res/drawable/ic_thumbs_up.xml new file mode 100644 index 0000000000..9761204ab6 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_thumbs_up.xml @@ -0,0 +1,12 @@ + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_train.xml b/matrix-sdk-android/src/main/res/drawable/ic_train.xml new file mode 100644 index 0000000000..e317ce1642 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_train.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_tree.xml b/matrix-sdk-android/src/main/res/drawable/ic_tree.xml new file mode 100644 index 0000000000..c5acc19a72 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_tree.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_trophy.xml b/matrix-sdk-android/src/main/res/drawable/ic_trophy.xml new file mode 100644 index 0000000000..631da7320d --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_trophy.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_trumpet.xml b/matrix-sdk-android/src/main/res/drawable/ic_trumpet.xml new file mode 100644 index 0000000000..84f95a8592 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_trumpet.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_turtle.xml b/matrix-sdk-android/src/main/res/drawable/ic_turtle.xml new file mode 100644 index 0000000000..1cedc1b6ad --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_turtle.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_umbrella.xml b/matrix-sdk-android/src/main/res/drawable/ic_umbrella.xml new file mode 100644 index 0000000000..ac1267cd3b --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_umbrella.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_unicorn.xml b/matrix-sdk-android/src/main/res/drawable/ic_unicorn.xml new file mode 100644 index 0000000000..19cef5d339 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_unicorn.xml @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/matrix-sdk-android/src/main/res/drawable/ic_wrench.xml b/matrix-sdk-android/src/main/res/drawable/ic_wrench.xml new file mode 100644 index 0000000000..ba3c4313a3 --- /dev/null +++ b/matrix-sdk-android/src/main/res/drawable/ic_wrench.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/debug/java/im/vector/riotx/features/debug/sas/SasEmojiItem.kt b/vector/src/debug/java/im/vector/riotx/features/debug/sas/SasEmojiItem.kt index 7403ead43c..cf9ca1032c 100644 --- a/vector/src/debug/java/im/vector/riotx/features/debug/sas/SasEmojiItem.kt +++ b/vector/src/debug/java/im/vector/riotx/features/debug/sas/SasEmojiItem.kt @@ -18,11 +18,14 @@ package im.vector.riotx.features.debug.sas import android.annotation.SuppressLint import android.widget.TextView +import androidx.core.content.ContextCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.matrix.android.api.session.crypto.verification.EmojiRepresentation import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel +import me.gujun.android.span.image +import me.gujun.android.span.span @EpoxyModelClass(layout = im.vector.riotx.R.layout.item_sas_emoji) abstract class SasEmojiItem : VectorEpoxyModel() { @@ -36,7 +39,12 @@ abstract class SasEmojiItem : VectorEpoxyModel() { override fun bind(holder: Holder) { super.bind(holder) holder.indexView.text = "$index:" - holder.emojiView.text = emojiRepresentation.emoji + holder.emojiView.text = span { + +emojiRepresentation.emoji + emojiRepresentation.drawableRes?.let { + image(ContextCompat.getDrawable(holder.view.context, it)!!) + } + } holder.textView.setText(emojiRepresentation.nameResId) holder.idView.text = holder.idView.resources.getResourceEntryName(emojiRepresentation.nameResId) } diff --git a/vector/src/main/assets/open_source_licenses.html b/vector/src/main/assets/open_source_licenses.html index e4fdc2f5ae..3af564aaca 100755 --- a/vector/src/main/assets/open_source_licenses.html +++ b/vector/src/main/assets/open_source_licenses.html @@ -23,6 +23,7 @@ } + @@ -566,5 +567,13 @@ Apache License of your accepting any such warranty or additional liability. +
+    CC-BY 4.0
+    
  • + Twitter/twemoji Graphics +
    +
  • +
    + diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/epoxy/BottomSheetVerificationEmojisItem.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/epoxy/BottomSheetVerificationEmojisItem.kt index 7d72486ccd..be14c7df3d 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/epoxy/BottomSheetVerificationEmojisItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/epoxy/BottomSheetVerificationEmojisItem.kt @@ -16,14 +16,21 @@ */ package im.vector.riotx.features.crypto.verification.epoxy +import android.content.Context import android.view.ViewGroup +import android.widget.ImageView import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.matrix.android.api.session.crypto.verification.EmojiRepresentation import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel +import me.gujun.android.span.Span +import me.gujun.android.span.image +import me.gujun.android.span.span /** * A emoji list for bottom sheet. @@ -40,26 +47,36 @@ abstract class BottomSheetVerificationEmojisItem : VectorEpoxyModel(R.id.item_emoji_tv).text = emojiRepresentation0.emoji - holder.emoji0View.findViewById(R.id.item_emoji_name_tv).setText(emojiRepresentation0.nameResId) + bindEmojiView(holder.emoji0View, emojiRepresentation0) + bindEmojiView(holder.emoji1View, emojiRepresentation1) + bindEmojiView(holder.emoji2View, emojiRepresentation2) + bindEmojiView(holder.emoji3View, emojiRepresentation3) + bindEmojiView(holder.emoji4View, emojiRepresentation4) + bindEmojiView(holder.emoji5View, emojiRepresentation5) + bindEmojiView(holder.emoji6View, emojiRepresentation6) + } - holder.emoji1View.findViewById(R.id.item_emoji_tv).text = emojiRepresentation1.emoji - holder.emoji1View.findViewById(R.id.item_emoji_name_tv).setText(emojiRepresentation1.nameResId) + private fun spanForRepresentation(context: Context, rep: EmojiRepresentation): Span { + return span { + if (rep.drawableRes != null) { + ContextCompat.getDrawable(context, rep.drawableRes!!)?.let { image(it) } + } else { + +rep.emoji + } + } + } - holder.emoji2View.findViewById(R.id.item_emoji_tv).text = emojiRepresentation2.emoji - holder.emoji2View.findViewById(R.id.item_emoji_name_tv).setText(emojiRepresentation2.nameResId) - - holder.emoji3View.findViewById(R.id.item_emoji_tv).text = emojiRepresentation3.emoji - holder.emoji3View.findViewById(R.id.item_emoji_name_tv)?.setText(emojiRepresentation3.nameResId) - - holder.emoji4View.findViewById(R.id.item_emoji_tv).text = emojiRepresentation4.emoji - holder.emoji4View.findViewById(R.id.item_emoji_name_tv).setText(emojiRepresentation4.nameResId) - - holder.emoji5View.findViewById(R.id.item_emoji_tv).text = emojiRepresentation5.emoji - holder.emoji5View.findViewById(R.id.item_emoji_name_tv).setText(emojiRepresentation5.nameResId) - - holder.emoji6View.findViewById(R.id.item_emoji_tv).text = emojiRepresentation6.emoji - holder.emoji6View.findViewById(R.id.item_emoji_name_tv).setText(emojiRepresentation6.nameResId) + private fun bindEmojiView(view: ViewGroup, rep: EmojiRepresentation) { + rep.drawableRes?.let { + view.findViewById(R.id.item_emoji_tv).isVisible = false + view.findViewById(R.id.item_emoji_image).isVisible = true + view.findViewById(R.id.item_emoji_image).setImageDrawable(ContextCompat.getDrawable(view.context, it)) + } ?: kotlin.run { + view.findViewById(R.id.item_emoji_tv).isVisible = true + view.findViewById(R.id.item_emoji_image).isVisible = false + view.findViewById(R.id.item_emoji_tv).text = rep.emoji + } + view.findViewById(R.id.item_emoji_name_tv).setText(rep.nameResId) } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/res/layout/item_emoji_verif.xml b/vector/src/main/res/layout/item_emoji_verif.xml index df9210f0ab..8ffeed3e3e 100644 --- a/vector/src/main/res/layout/item_emoji_verif.xml +++ b/vector/src/main/res/layout/item_emoji_verif.xml @@ -15,6 +15,19 @@ android:layout_gravity="center" android:textColor="@color/black" android:textSize="40dp" + tools:visibility="gone" + tools:ignore="SpUsage" + tools:text="🌵" /> + + From ede899d78e784d5a47ce5072f6f87590f6aa9606 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 10 Apr 2020 11:09:16 +0200 Subject: [PATCH 13/20] Fix / Bad smiley emojii --- .../internal/crypto/verification/VerificationEmoji.kt | 2 +- matrix-sdk-android/src/main/res/drawable/ic_smiley.xml | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt index 738b56dc5b..8da633acf9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt @@ -50,7 +50,7 @@ internal fun getEmojiForCode(code: Int): EmojiRepresentation { 27 -> EmojiRepresentation("🍕", R.string.verification_emoji_pizza, R.drawable.ic_pizza) 28 -> EmojiRepresentation("🎂", R.string.verification_emoji_cake, R.drawable.ic_cake) 29 -> EmojiRepresentation("❤️", R.string.verification_emoji_heart, R.drawable.ic_heart) - 30 -> EmojiRepresentation("😀", R.string.verification_emoji_smiley, R.drawable.ic_smiley) + 30 -> EmojiRepresentation("🙂", R.string.verification_emoji_smiley, R.drawable.ic_smiley) 31 -> EmojiRepresentation("🤖", R.string.verification_emoji_robot, R.drawable.ic_robot) 32 -> EmojiRepresentation("🎩", R.string.verification_emoji_hat, R.drawable.ic_hat) 33 -> EmojiRepresentation("👓", R.string.verification_emoji_glasses, R.drawable.ic_glasses) diff --git a/matrix-sdk-android/src/main/res/drawable/ic_smiley.xml b/matrix-sdk-android/src/main/res/drawable/ic_smiley.xml index 28c2394b99..087adc8c6d 100644 --- a/matrix-sdk-android/src/main/res/drawable/ic_smiley.xml +++ b/matrix-sdk-android/src/main/res/drawable/ic_smiley.xml @@ -7,11 +7,8 @@ android:pathData="M18,18m-18,0a18,18 0,1 1,36 0a18,18 0,1 1,-36 0" android:fillColor="#FFCC4D"/> - From 8357abd45508795c5247fd0530c8f7f0c3bbe69c Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 10 Apr 2020 11:18:41 +0200 Subject: [PATCH 14/20] Added prefix to resources to avoid accidental override --- .../crypto/verification/VerificationEmoji.kt | 128 +++++++++--------- ...plane.xml => ic_verification_airplane.xml} | 0 ..._anchor.xml => ic_verification_anchor.xml} | 0 ...ic_apple.xml => ic_verification_apple.xml} | 0 .../{ic_ball.xml => ic_verification_ball.xml} | 0 ..._banana.xml => ic_verification_banana.xml} | 0 .../{ic_bell.xml => ic_verification_bell.xml} | 0 ...icycle.xml => ic_verification_bicycle.xml} | 0 .../{ic_book.xml => ic_verification_book.xml} | 0 ...rfly.xml => ic_verification_butterfly.xml} | 0 ..._cactus.xml => ic_verification_cactus.xml} | 0 .../{ic_cake.xml => ic_verification_cake.xml} | 0 .../{ic_cat.xml => ic_verification_cat.xml} | 0 ...ic_clock.xml => ic_verification_clock.xml} | 0 ...ic_cloud.xml => ic_verification_cloud.xml} | 0 .../{ic_corn.xml => ic_verification_corn.xml} | 0 .../{ic_dog.xml => ic_verification_dog.xml} | 0 ...phant.xml => ic_verification_elephant.xml} | 0 .../{ic_fire.xml => ic_verification_fire.xml} | 0 .../{ic_fish.xml => ic_verification_fish.xml} | 0 .../{ic_flag.xml => ic_verification_flag.xml} | 0 ..._flower.xml => ic_verification_flower.xml} | 0 ..._folder.xml => ic_verification_folder.xml} | 0 .../{ic_gift.xml => ic_verification_gift.xml} | 0 ...lasses.xml => ic_verification_glasses.xml} | 0 ...ic_globe.xml => ic_verification_globe.xml} | 0 ..._guitar.xml => ic_verification_guitar.xml} | 0 ..._hammer.xml => ic_verification_hammer.xml} | 0 .../{ic_hat.xml => ic_verification_hat.xml} | 0 ...hone.xml => ic_verification_headphone.xml} | 0 ...ic_heart.xml => ic_verification_heart.xml} | 0 ...ic_horse.xml => ic_verification_horse.xml} | 0 ...lass.xml => ic_verification_hourglass.xml} | 0 .../{ic_key.xml => ic_verification_key.xml} | 0 ...ulb.xml => ic_verification_light_bulb.xml} | 0 .../{ic_lion.xml => ic_verification_lion.xml} | 0 .../{ic_lock.xml => ic_verification_lock.xml} | 0 .../{ic_moon.xml => ic_verification_moon.xml} | 0 ...hroom.xml => ic_verification_mushroom.xml} | 0 ...ctopus.xml => ic_verification_octopus.xml} | 0 ...ic_panda.xml => ic_verification_panda.xml} | 0 ...clip.xml => ic_verification_paperclip.xml} | 0 ..._pencil.xml => ic_verification_pencil.xml} | 0 ...enguin.xml => ic_verification_penguin.xml} | 0 ...ic_phone.xml => ic_verification_phone.xml} | 0 .../{ic_pig.xml => ic_verification_pig.xml} | 0 .../{ic_pin.xml => ic_verification_pin.xml} | 0 ...ic_pizza.xml => ic_verification_pizza.xml} | 0 ..._rabbit.xml => ic_verification_rabbit.xml} | 0 ...ic_robot.xml => ic_verification_robot.xml} | 0 ..._rocket.xml => ic_verification_rocket.xml} | 0 ...ooster.xml => ic_verification_rooster.xml} | 0 ...ic_santa.xml => ic_verification_santa.xml} | 0 ...ssors.xml => ic_verification_scissors.xml} | 0 ..._smiley.xml => ic_verification_smiley.xml} | 0 ...rry.xml => ic_verification_strawberry.xml} | 0 ...s_up.xml => ic_verification_thumbs_up.xml} | 0 ...ic_train.xml => ic_verification_train.xml} | 0 .../{ic_tree.xml => ic_verification_tree.xml} | 0 ..._trophy.xml => ic_verification_trophy.xml} | 0 ...rumpet.xml => ic_verification_trumpet.xml} | 0 ..._turtle.xml => ic_verification_turtle.xml} | 0 ...rella.xml => ic_verification_umbrella.xml} | 0 ...nicorn.xml => ic_verification_unicorn.xml} | 0 ..._wrench.xml => ic_verification_wrench.xml} | 0 .../src/main/res/layout/item_emoji_verif.xml | 2 +- 66 files changed, 65 insertions(+), 65 deletions(-) rename matrix-sdk-android/src/main/res/drawable/{ic_airplane.xml => ic_verification_airplane.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_anchor.xml => ic_verification_anchor.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_apple.xml => ic_verification_apple.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_ball.xml => ic_verification_ball.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_banana.xml => ic_verification_banana.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_bell.xml => ic_verification_bell.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_bicycle.xml => ic_verification_bicycle.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_book.xml => ic_verification_book.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_butterfly.xml => ic_verification_butterfly.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_cactus.xml => ic_verification_cactus.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_cake.xml => ic_verification_cake.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_cat.xml => ic_verification_cat.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_clock.xml => ic_verification_clock.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_cloud.xml => ic_verification_cloud.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_corn.xml => ic_verification_corn.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_dog.xml => ic_verification_dog.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_elephant.xml => ic_verification_elephant.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_fire.xml => ic_verification_fire.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_fish.xml => ic_verification_fish.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_flag.xml => ic_verification_flag.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_flower.xml => ic_verification_flower.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_folder.xml => ic_verification_folder.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_gift.xml => ic_verification_gift.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_glasses.xml => ic_verification_glasses.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_globe.xml => ic_verification_globe.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_guitar.xml => ic_verification_guitar.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_hammer.xml => ic_verification_hammer.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_hat.xml => ic_verification_hat.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_headphone.xml => ic_verification_headphone.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_heart.xml => ic_verification_heart.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_horse.xml => ic_verification_horse.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_hourglass.xml => ic_verification_hourglass.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_key.xml => ic_verification_key.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_light_bulb.xml => ic_verification_light_bulb.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_lion.xml => ic_verification_lion.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_lock.xml => ic_verification_lock.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_moon.xml => ic_verification_moon.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_mushroom.xml => ic_verification_mushroom.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_octopus.xml => ic_verification_octopus.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_panda.xml => ic_verification_panda.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_paperclip.xml => ic_verification_paperclip.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_pencil.xml => ic_verification_pencil.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_penguin.xml => ic_verification_penguin.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_phone.xml => ic_verification_phone.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_pig.xml => ic_verification_pig.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_pin.xml => ic_verification_pin.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_pizza.xml => ic_verification_pizza.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_rabbit.xml => ic_verification_rabbit.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_robot.xml => ic_verification_robot.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_rocket.xml => ic_verification_rocket.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_rooster.xml => ic_verification_rooster.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_santa.xml => ic_verification_santa.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_scissors.xml => ic_verification_scissors.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_smiley.xml => ic_verification_smiley.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_strawberry.xml => ic_verification_strawberry.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_thumbs_up.xml => ic_verification_thumbs_up.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_train.xml => ic_verification_train.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_tree.xml => ic_verification_tree.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_trophy.xml => ic_verification_trophy.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_trumpet.xml => ic_verification_trumpet.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_turtle.xml => ic_verification_turtle.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_umbrella.xml => ic_verification_umbrella.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_unicorn.xml => ic_verification_unicorn.xml} (100%) rename matrix-sdk-android/src/main/res/drawable/{ic_wrench.xml => ic_verification_wrench.xml} (100%) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt index 8da633acf9..396b609f41 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationEmoji.kt @@ -20,69 +20,69 @@ import im.vector.matrix.android.api.session.crypto.verification.EmojiRepresentat internal fun getEmojiForCode(code: Int): EmojiRepresentation { return when (code % 64) { - 0 -> EmojiRepresentation("🐶", R.string.verification_emoji_dog, R.drawable.ic_dog) - 1 -> EmojiRepresentation("🐱", R.string.verification_emoji_cat, R.drawable.ic_cat) - 2 -> EmojiRepresentation("🦁", R.string.verification_emoji_lion, R.drawable.ic_lion) - 3 -> EmojiRepresentation("🐎", R.string.verification_emoji_horse, R.drawable.ic_horse) - 4 -> EmojiRepresentation("🦄", R.string.verification_emoji_unicorn, R.drawable.ic_unicorn) - 5 -> EmojiRepresentation("🐷", R.string.verification_emoji_pig, R.drawable.ic_pig) - 6 -> EmojiRepresentation("🐘", R.string.verification_emoji_elephant, R.drawable.ic_elephant) - 7 -> EmojiRepresentation("🐰", R.string.verification_emoji_rabbit, R.drawable.ic_rabbit) - 8 -> EmojiRepresentation("🐼", R.string.verification_emoji_panda, R.drawable.ic_panda) - 9 -> EmojiRepresentation("🐓", R.string.verification_emoji_rooster, R.drawable.ic_rooster) - 10 -> EmojiRepresentation("🐧", R.string.verification_emoji_penguin, R.drawable.ic_penguin) - 11 -> EmojiRepresentation("🐢", R.string.verification_emoji_turtle, R.drawable.ic_turtle) - 12 -> EmojiRepresentation("🐟", R.string.verification_emoji_fish, R.drawable.ic_fish) - 13 -> EmojiRepresentation("🐙", R.string.verification_emoji_octopus, R.drawable.ic_octopus) - 14 -> EmojiRepresentation("🦋", R.string.verification_emoji_butterfly, R.drawable.ic_butterfly) - 15 -> EmojiRepresentation("🌷", R.string.verification_emoji_flower, R.drawable.ic_flower) - 16 -> EmojiRepresentation("🌳", R.string.verification_emoji_tree, R.drawable.ic_tree) - 17 -> EmojiRepresentation("🌵", R.string.verification_emoji_cactus, R.drawable.ic_cactus) - 18 -> EmojiRepresentation("🍄", R.string.verification_emoji_mushroom, R.drawable.ic_mushroom) - 19 -> EmojiRepresentation("🌏", R.string.verification_emoji_globe, R.drawable.ic_globe) - 20 -> EmojiRepresentation("🌙", R.string.verification_emoji_moon, R.drawable.ic_moon) - 21 -> EmojiRepresentation("☁️", R.string.verification_emoji_cloud, R.drawable.ic_cloud) - 22 -> EmojiRepresentation("🔥", R.string.verification_emoji_fire, R.drawable.ic_fire) - 23 -> EmojiRepresentation("🍌", R.string.verification_emoji_banana, R.drawable.ic_banana) - 24 -> EmojiRepresentation("🍎", R.string.verification_emoji_apple, R.drawable.ic_apple) - 25 -> EmojiRepresentation("🍓", R.string.verification_emoji_strawberry, R.drawable.ic_strawberry) - 26 -> EmojiRepresentation("🌽", R.string.verification_emoji_corn, R.drawable.ic_corn) - 27 -> EmojiRepresentation("🍕", R.string.verification_emoji_pizza, R.drawable.ic_pizza) - 28 -> EmojiRepresentation("🎂", R.string.verification_emoji_cake, R.drawable.ic_cake) - 29 -> EmojiRepresentation("❤️", R.string.verification_emoji_heart, R.drawable.ic_heart) - 30 -> EmojiRepresentation("🙂", R.string.verification_emoji_smiley, R.drawable.ic_smiley) - 31 -> EmojiRepresentation("🤖", R.string.verification_emoji_robot, R.drawable.ic_robot) - 32 -> EmojiRepresentation("🎩", R.string.verification_emoji_hat, R.drawable.ic_hat) - 33 -> EmojiRepresentation("👓", R.string.verification_emoji_glasses, R.drawable.ic_glasses) - 34 -> EmojiRepresentation("🔧", R.string.verification_emoji_wrench, R.drawable.ic_wrench) - 35 -> EmojiRepresentation("🎅", R.string.verification_emoji_santa, R.drawable.ic_santa) - 36 -> EmojiRepresentation("👍", R.string.verification_emoji_thumbsup, R.drawable.ic_thumbs_up) - 37 -> EmojiRepresentation("☂️", R.string.verification_emoji_umbrella, R.drawable.ic_umbrella) - 38 -> EmojiRepresentation("⌛", R.string.verification_emoji_hourglass, R.drawable.ic_hourglass) - 39 -> EmojiRepresentation("⏰", R.string.verification_emoji_clock, R.drawable.ic_clock) - 40 -> EmojiRepresentation("🎁", R.string.verification_emoji_gift, R.drawable.ic_gift) - 41 -> EmojiRepresentation("💡", R.string.verification_emoji_lightbulb, R.drawable.ic_light_bulb) - 42 -> EmojiRepresentation("📕", R.string.verification_emoji_book, R.drawable.ic_book) - 43 -> EmojiRepresentation("✏️", R.string.verification_emoji_pencil, R.drawable.ic_pencil) - 44 -> EmojiRepresentation("📎", R.string.verification_emoji_paperclip, R.drawable.ic_paperclip) - 45 -> EmojiRepresentation("✂️", R.string.verification_emoji_scissors, R.drawable.ic_scissors) - 46 -> EmojiRepresentation("🔒", R.string.verification_emoji_lock, R.drawable.ic_lock) - 47 -> EmojiRepresentation("🔑", R.string.verification_emoji_key, R.drawable.ic_key) - 48 -> EmojiRepresentation("🔨", R.string.verification_emoji_hammer, R.drawable.ic_hammer) - 49 -> EmojiRepresentation("☎️", R.string.verification_emoji_telephone, R.drawable.ic_phone) - 50 -> EmojiRepresentation("🏁", R.string.verification_emoji_flag, R.drawable.ic_flag) - 51 -> EmojiRepresentation("🚂", R.string.verification_emoji_train, R.drawable.ic_train) - 52 -> EmojiRepresentation("🚲", R.string.verification_emoji_bicycle, R.drawable.ic_bicycle) - 53 -> EmojiRepresentation("✈️", R.string.verification_emoji_airplane, R.drawable.ic_airplane) - 54 -> EmojiRepresentation("🚀", R.string.verification_emoji_rocket, R.drawable.ic_rocket) - 55 -> EmojiRepresentation("🏆", R.string.verification_emoji_trophy, R.drawable.ic_trophy) - 56 -> EmojiRepresentation("⚽", R.string.verification_emoji_ball, R.drawable.ic_ball) - 57 -> EmojiRepresentation("🎸", R.string.verification_emoji_guitar, R.drawable.ic_guitar) - 58 -> EmojiRepresentation("🎺", R.string.verification_emoji_trumpet, R.drawable.ic_trumpet) - 59 -> EmojiRepresentation("🔔", R.string.verification_emoji_bell, R.drawable.ic_bell) - 60 -> EmojiRepresentation("⚓", R.string.verification_emoji_anchor, R.drawable.ic_anchor) - 61 -> EmojiRepresentation("🎧", R.string.verification_emoji_headphone, R.drawable.ic_headphone) - 62 -> EmojiRepresentation("📁", R.string.verification_emoji_folder, R.drawable.ic_folder) - /* 63 */ else -> EmojiRepresentation("📌", R.string.verification_emoji_pin, R.drawable.ic_pin) + 0 -> EmojiRepresentation("🐶", R.string.verification_emoji_dog, R.drawable.ic_verification_dog) + 1 -> EmojiRepresentation("🐱", R.string.verification_emoji_cat, R.drawable.ic_verification_cat) + 2 -> EmojiRepresentation("🦁", R.string.verification_emoji_lion, R.drawable.ic_verification_lion) + 3 -> EmojiRepresentation("🐎", R.string.verification_emoji_horse, R.drawable.ic_verification_horse) + 4 -> EmojiRepresentation("🦄", R.string.verification_emoji_unicorn, R.drawable.ic_verification_unicorn) + 5 -> EmojiRepresentation("🐷", R.string.verification_emoji_pig, R.drawable.ic_verification_pig) + 6 -> EmojiRepresentation("🐘", R.string.verification_emoji_elephant, R.drawable.ic_verification_elephant) + 7 -> EmojiRepresentation("🐰", R.string.verification_emoji_rabbit, R.drawable.ic_verification_rabbit) + 8 -> EmojiRepresentation("🐼", R.string.verification_emoji_panda, R.drawable.ic_verification_panda) + 9 -> EmojiRepresentation("🐓", R.string.verification_emoji_rooster, R.drawable.ic_verification_rooster) + 10 -> EmojiRepresentation("🐧", R.string.verification_emoji_penguin, R.drawable.ic_verification_penguin) + 11 -> EmojiRepresentation("🐢", R.string.verification_emoji_turtle, R.drawable.ic_verification_turtle) + 12 -> EmojiRepresentation("🐟", R.string.verification_emoji_fish, R.drawable.ic_verification_fish) + 13 -> EmojiRepresentation("🐙", R.string.verification_emoji_octopus, R.drawable.ic_verification_octopus) + 14 -> EmojiRepresentation("🦋", R.string.verification_emoji_butterfly, R.drawable.ic_verification_butterfly) + 15 -> EmojiRepresentation("🌷", R.string.verification_emoji_flower, R.drawable.ic_verification_flower) + 16 -> EmojiRepresentation("🌳", R.string.verification_emoji_tree, R.drawable.ic_verification_tree) + 17 -> EmojiRepresentation("🌵", R.string.verification_emoji_cactus, R.drawable.ic_verification_cactus) + 18 -> EmojiRepresentation("🍄", R.string.verification_emoji_mushroom, R.drawable.ic_verification_mushroom) + 19 -> EmojiRepresentation("🌏", R.string.verification_emoji_globe, R.drawable.ic_verification_globe) + 20 -> EmojiRepresentation("🌙", R.string.verification_emoji_moon, R.drawable.ic_verification_moon) + 21 -> EmojiRepresentation("☁️", R.string.verification_emoji_cloud, R.drawable.ic_verification_cloud) + 22 -> EmojiRepresentation("🔥", R.string.verification_emoji_fire, R.drawable.ic_verification_fire) + 23 -> EmojiRepresentation("🍌", R.string.verification_emoji_banana, R.drawable.ic_verification_banana) + 24 -> EmojiRepresentation("🍎", R.string.verification_emoji_apple, R.drawable.ic_verification_apple) + 25 -> EmojiRepresentation("🍓", R.string.verification_emoji_strawberry, R.drawable.ic_verification_strawberry) + 26 -> EmojiRepresentation("🌽", R.string.verification_emoji_corn, R.drawable.ic_verification_corn) + 27 -> EmojiRepresentation("🍕", R.string.verification_emoji_pizza, R.drawable.ic_verification_pizza) + 28 -> EmojiRepresentation("🎂", R.string.verification_emoji_cake, R.drawable.ic_verification_cake) + 29 -> EmojiRepresentation("❤️", R.string.verification_emoji_heart, R.drawable.ic_verification_heart) + 30 -> EmojiRepresentation("🙂", R.string.verification_emoji_smiley, R.drawable.ic_verification_smiley) + 31 -> EmojiRepresentation("🤖", R.string.verification_emoji_robot, R.drawable.ic_verification_robot) + 32 -> EmojiRepresentation("🎩", R.string.verification_emoji_hat, R.drawable.ic_verification_hat) + 33 -> EmojiRepresentation("👓", R.string.verification_emoji_glasses, R.drawable.ic_verification_glasses) + 34 -> EmojiRepresentation("🔧", R.string.verification_emoji_wrench, R.drawable.ic_verification_wrench) + 35 -> EmojiRepresentation("🎅", R.string.verification_emoji_santa, R.drawable.ic_verification_santa) + 36 -> EmojiRepresentation("👍", R.string.verification_emoji_thumbsup, R.drawable.ic_verification_thumbs_up) + 37 -> EmojiRepresentation("☂️", R.string.verification_emoji_umbrella, R.drawable.ic_verification_umbrella) + 38 -> EmojiRepresentation("⌛", R.string.verification_emoji_hourglass, R.drawable.ic_verification_hourglass) + 39 -> EmojiRepresentation("⏰", R.string.verification_emoji_clock, R.drawable.ic_verification_clock) + 40 -> EmojiRepresentation("🎁", R.string.verification_emoji_gift, R.drawable.ic_verification_gift) + 41 -> EmojiRepresentation("💡", R.string.verification_emoji_lightbulb, R.drawable.ic_verification_light_bulb) + 42 -> EmojiRepresentation("📕", R.string.verification_emoji_book, R.drawable.ic_verification_book) + 43 -> EmojiRepresentation("✏️", R.string.verification_emoji_pencil, R.drawable.ic_verification_pencil) + 44 -> EmojiRepresentation("📎", R.string.verification_emoji_paperclip, R.drawable.ic_verification_paperclip) + 45 -> EmojiRepresentation("✂️", R.string.verification_emoji_scissors, R.drawable.ic_verification_scissors) + 46 -> EmojiRepresentation("🔒", R.string.verification_emoji_lock, R.drawable.ic_verification_lock) + 47 -> EmojiRepresentation("🔑", R.string.verification_emoji_key, R.drawable.ic_verification_key) + 48 -> EmojiRepresentation("🔨", R.string.verification_emoji_hammer, R.drawable.ic_verification_hammer) + 49 -> EmojiRepresentation("☎️", R.string.verification_emoji_telephone, R.drawable.ic_verification_phone) + 50 -> EmojiRepresentation("🏁", R.string.verification_emoji_flag, R.drawable.ic_verification_flag) + 51 -> EmojiRepresentation("🚂", R.string.verification_emoji_train, R.drawable.ic_verification_train) + 52 -> EmojiRepresentation("🚲", R.string.verification_emoji_bicycle, R.drawable.ic_verification_bicycle) + 53 -> EmojiRepresentation("✈️", R.string.verification_emoji_airplane, R.drawable.ic_verification_airplane) + 54 -> EmojiRepresentation("🚀", R.string.verification_emoji_rocket, R.drawable.ic_verification_rocket) + 55 -> EmojiRepresentation("🏆", R.string.verification_emoji_trophy, R.drawable.ic_verification_trophy) + 56 -> EmojiRepresentation("⚽", R.string.verification_emoji_ball, R.drawable.ic_verification_ball) + 57 -> EmojiRepresentation("🎸", R.string.verification_emoji_guitar, R.drawable.ic_verification_guitar) + 58 -> EmojiRepresentation("🎺", R.string.verification_emoji_trumpet, R.drawable.ic_verification_trumpet) + 59 -> EmojiRepresentation("🔔", R.string.verification_emoji_bell, R.drawable.ic_verification_bell) + 60 -> EmojiRepresentation("⚓", R.string.verification_emoji_anchor, R.drawable.ic_verification_anchor) + 61 -> EmojiRepresentation("🎧", R.string.verification_emoji_headphone, R.drawable.ic_verification_headphone) + 62 -> EmojiRepresentation("📁", R.string.verification_emoji_folder, R.drawable.ic_verification_folder) + /* 63 */ else -> EmojiRepresentation("📌", R.string.verification_emoji_pin, R.drawable.ic_verification_pin) } } diff --git a/matrix-sdk-android/src/main/res/drawable/ic_airplane.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_airplane.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_airplane.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_airplane.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_anchor.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_anchor.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_anchor.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_anchor.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_apple.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_apple.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_apple.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_apple.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_ball.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_ball.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_ball.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_ball.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_banana.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_banana.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_banana.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_banana.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_bell.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_bell.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_bell.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_bell.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_bicycle.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_bicycle.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_bicycle.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_bicycle.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_book.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_book.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_book.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_book.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_butterfly.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_butterfly.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_butterfly.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_butterfly.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_cactus.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_cactus.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_cactus.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_cactus.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_cake.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_cake.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_cake.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_cake.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_cat.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_cat.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_cat.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_cat.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_clock.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_clock.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_clock.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_clock.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_cloud.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_cloud.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_cloud.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_cloud.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_corn.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_corn.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_corn.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_corn.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_dog.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_dog.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_dog.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_dog.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_elephant.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_elephant.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_elephant.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_elephant.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_fire.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_fire.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_fire.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_fire.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_fish.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_fish.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_fish.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_fish.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_flag.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_flag.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_flag.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_flag.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_flower.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_flower.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_flower.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_flower.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_folder.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_folder.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_folder.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_folder.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_gift.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_gift.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_gift.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_gift.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_glasses.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_glasses.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_glasses.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_glasses.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_globe.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_globe.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_globe.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_globe.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_guitar.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_guitar.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_guitar.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_guitar.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_hammer.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_hammer.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_hammer.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_hammer.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_hat.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_hat.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_hat.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_hat.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_headphone.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_headphone.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_headphone.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_headphone.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_heart.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_heart.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_heart.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_heart.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_horse.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_horse.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_horse.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_horse.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_hourglass.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_hourglass.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_hourglass.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_hourglass.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_key.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_key.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_key.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_key.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_light_bulb.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_light_bulb.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_light_bulb.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_light_bulb.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_lion.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_lion.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_lion.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_lion.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_lock.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_lock.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_lock.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_lock.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_moon.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_moon.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_moon.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_moon.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_mushroom.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_mushroom.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_mushroom.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_mushroom.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_octopus.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_octopus.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_octopus.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_octopus.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_panda.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_panda.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_panda.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_panda.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_paperclip.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_paperclip.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_paperclip.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_paperclip.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_pencil.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_pencil.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_pencil.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_pencil.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_penguin.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_penguin.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_penguin.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_penguin.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_phone.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_phone.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_phone.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_phone.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_pig.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_pig.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_pig.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_pig.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_pin.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_pin.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_pin.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_pin.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_pizza.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_pizza.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_pizza.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_pizza.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_rabbit.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_rabbit.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_rabbit.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_rabbit.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_robot.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_robot.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_robot.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_robot.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_rocket.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_rocket.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_rocket.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_rocket.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_rooster.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_rooster.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_rooster.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_rooster.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_santa.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_santa.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_santa.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_santa.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_scissors.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_scissors.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_scissors.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_scissors.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_smiley.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_smiley.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_smiley.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_smiley.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_strawberry.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_strawberry.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_strawberry.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_strawberry.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_thumbs_up.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_thumbs_up.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_thumbs_up.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_thumbs_up.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_train.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_train.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_train.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_train.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_tree.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_tree.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_tree.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_tree.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_trophy.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_trophy.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_trophy.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_trophy.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_trumpet.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_trumpet.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_trumpet.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_trumpet.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_turtle.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_turtle.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_turtle.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_turtle.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_umbrella.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_umbrella.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_umbrella.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_umbrella.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_unicorn.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_unicorn.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_unicorn.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_unicorn.xml diff --git a/matrix-sdk-android/src/main/res/drawable/ic_wrench.xml b/matrix-sdk-android/src/main/res/drawable/ic_verification_wrench.xml similarity index 100% rename from matrix-sdk-android/src/main/res/drawable/ic_wrench.xml rename to matrix-sdk-android/src/main/res/drawable/ic_verification_wrench.xml diff --git a/vector/src/main/res/layout/item_emoji_verif.xml b/vector/src/main/res/layout/item_emoji_verif.xml index 8ffeed3e3e..ff883e6de1 100644 --- a/vector/src/main/res/layout/item_emoji_verif.xml +++ b/vector/src/main/res/layout/item_emoji_verif.xml @@ -25,7 +25,7 @@ android:layout_margin="2dp" android:layout_height="54dp" android:layout_gravity="center" - android:src="@drawable/ic_lion" + android:src="@drawable/ic_verification_cactus" tools:visibility="visible" android:visibility="gone" tools:ignore="SpUsage" From f5dc0b38ff5aa2a086dff0a384d34f518fca07dd Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 10 Apr 2020 11:47:54 +0200 Subject: [PATCH 15/20] Code review --- .../verification/VerificationBottomSheetViewModel.kt | 7 +++++-- vector/src/main/res/values/strings_riotX.xml | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt index 71a9ec73e7..c7a5b3a011 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt @@ -52,8 +52,10 @@ import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersio import im.vector.matrix.android.internal.crypto.keysbackup.util.computeRecoveryKey import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult import im.vector.matrix.android.internal.util.awaitCallback +import im.vector.riotx.R import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.platform.VectorViewModel +import im.vector.riotx.core.resources.StringProvider import kotlinx.coroutines.launch import timber.log.Timber @@ -78,7 +80,8 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( @Assisted initialState: VerificationBottomSheetViewState, @Assisted val args: VerificationBottomSheet.VerificationArgs, private val session: Session, - private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider) + private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider, + private val stringProvider: StringProvider) : VectorViewModel(initialState), VerificationService.Listener { @@ -373,7 +376,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( // try to get keybackup key } else { // POP UP something - _viewEvents.post(VerificationBottomSheetViewEvents.ModalError("Failed to import keys")) + _viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys))) } // try the keybackup diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 606a1b95f6..a3f57b7716 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -94,6 +94,8 @@ The encryption used by this room is not supported %s created and configured the room. + Failed to import keys + From 5081361c2d17fa3a46b3f455b65a5c25dff58641 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 9 Apr 2020 16:29:52 +0200 Subject: [PATCH 16/20] Update Scan confirm flow --- .../verification/VerificationTxState.kt | 1 + .../DefaultVerificationService.kt | 73 +++++++++++++------ .../DefaultVerificationTransaction.kt | 13 +--- .../verification/VerificationInfoDone.kt | 10 +-- .../DefaultQrCodeVerificationTransaction.kt | 23 ++++-- .../im/vector/riotx/core/di/FragmentModule.kt | 6 ++ .../verification/VerificationBottomSheet.kt | 8 ++ .../VerificationQRWaitingController.kt | 60 +++++++++++++++ .../VerificationQRWaitingFragment.kt | 59 +++++++++++++++ .../VerificationQrScannedByOtherController.kt | 17 ++++- .../VerificationQrScannedByOtherFragment.kt | 6 +- vector/src/main/res/values/strings.xml | 2 +- vector/src/main/res/values/strings_riotX.xml | 5 ++ 13 files changed, 236 insertions(+), 47 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQRWaitingFragment.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/verification/VerificationTxState.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/verification/VerificationTxState.kt index aaaf227187..868ec5a3e2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/verification/VerificationTxState.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/verification/VerificationTxState.kt @@ -43,6 +43,7 @@ sealed class VerificationTxState { // Will be used to ask the user if the other user has correctly scanned object QrScannedByOther : VerificationQrTxState() + object WaitingOtherReciprocateConfirm : VerificationQrTxState() // Terminal states abstract class TerminalTxState : VerificationTxState() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt index db6c224019..77dcc483bd 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt @@ -646,9 +646,7 @@ internal class DefaultVerificationService @Inject constructor( )) } - if (existingTransaction is SASDefaultVerificationTransaction) { - existingTransaction.state = VerificationTxState.Cancelled(safeValueOf(cancelReq.code), false) - } + existingTransaction?.state = VerificationTxState.Cancelled(safeValueOf(cancelReq.code), false) } private fun onRoomAcceptReceived(event: Event) { @@ -792,26 +790,53 @@ internal class DefaultVerificationService @Inject constructor( private fun onDoneReceived(event: Event) { Timber.v("## onDoneReceived") val doneReq = event.getClearContent().toModel()?.asValidObject() - if (doneReq == null || event.senderId != userId) { + if (doneReq == null || event.senderId == null) { // ignore Timber.e("## SAS Received invalid done request") return } - // We only send gossiping request when the other sent us a done - // We can ask without checking too much thinks (like trust), because we will check validity of secret on reception - getExistingTransaction(userId, doneReq.transactionId) - ?: getOldTransaction(userId, doneReq.transactionId) - ?.let { vt -> - val otherDeviceId = vt.otherDeviceId - if (!crossSigningService.canCrossSign()) { - outgoingGossipingRequestManager.sendSecretShareRequest(SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId - ?: "*"))) - outgoingGossipingRequestManager.sendSecretShareRequest(USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId + handleDoneReceived(event.senderId, doneReq) + + if (event.senderId == userId) { + // We only send gossiping request when the other sent us a done + // We can ask without checking too much thinks (like trust), because we will check validity of secret on reception + getExistingTransaction(userId, doneReq.transactionId) + ?: getOldTransaction(userId, doneReq.transactionId) + ?.let { vt -> + val otherDeviceId = vt.otherDeviceId + if (!crossSigningService.canCrossSign()) { + outgoingGossipingRequestManager.sendSecretShareRequest(SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId + ?: "*"))) + outgoingGossipingRequestManager.sendSecretShareRequest(USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId + ?: "*"))) + } + outgoingGossipingRequestManager.sendSecretShareRequest(KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) } - outgoingGossipingRequestManager.sendSecretShareRequest(KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) - } + } + } + + private fun handleDoneReceived(senderId: String, doneReq: ValidVerificationDone) { + Timber.v("## SAS Done receieved $doneReq") + val existing = getExistingTransaction(senderId, doneReq.transactionId) + if (existing == null) { + Timber.e("## SAS Received invalid Done request") + return + } + if (existing is DefaultQrCodeVerificationTransaction) { + existing.onDoneReceived() + } else { + // SAS do not care for now? + } + + // Now transactions are udated, let's also update Requests + val existingRequest = getExistingVerificationRequest(senderId)?.find { it.transactionId == doneReq.transactionId } + if (existingRequest == null) { + Timber.e("## SAS Received Done for unknown request txId:${doneReq.transactionId}") + return + } + updatePendingRequest(existingRequest.copy(isSuccessful = true)) } private fun onRoomDoneReceived(event: Event) { @@ -993,14 +1018,14 @@ internal class DefaultVerificationService @Inject constructor( ) } - private fun handleDoneReceived(senderId: String, doneInfo: ValidVerificationDone) { - val existingRequest = getExistingVerificationRequest(senderId)?.find { it.transactionId == doneInfo.transactionId } - if (existingRequest == null) { - Timber.e("## SAS Received Done for unknown request txId:${doneInfo.transactionId}") - return - } - updatePendingRequest(existingRequest.copy(isSuccessful = true)) - } +// private fun handleDoneReceived(senderId: String, doneInfo: ValidVerificationDone) { +// val existingRequest = getExistingVerificationRequest(senderId)?.find { it.transactionId == doneInfo.transactionId } +// if (existingRequest == null) { +// Timber.e("## SAS Received Done for unknown request txId:${doneInfo.transactionId}") +// return +// } +// updatePendingRequest(existingRequest.copy(isSuccessful = true)) +// } // TODO All this methods should be delegated to a TransactionStore override fun getExistingTransaction(otherUserId: String, tid: String): VerificationTransaction? { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationTransaction.kt index 29cfcd2383..eb78aee42d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationTransaction.kt @@ -57,7 +57,7 @@ internal abstract class DefaultVerificationTransaction( protected fun trust(canTrustOtherUserMasterKey: Boolean, toVerifyDeviceIds: List, - eventuallyMarkMyMasterKeyAsTrusted: Boolean) { + eventuallyMarkMyMasterKeyAsTrusted: Boolean, autoDone : Boolean = true) { Timber.d("## Verification: trust ($otherUserId,$otherDeviceId) , verifiedDevices:$toVerifyDeviceIds") Timber.d("## Verification: trust Mark myMSK trusted $eventuallyMarkMyMasterKeyAsTrusted") @@ -97,14 +97,9 @@ internal abstract class DefaultVerificationTransaction( }) } - state = VerificationTxState.Verified - - transport.done(transactionId) { -// if (otherUserId == userId && !crossSigningService.canCrossSign()) { -// outgoingGossipingRequestManager.sendSecretShareRequest(SELF_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) -// outgoingGossipingRequestManager.sendSecretShareRequest(USER_SIGNING_KEY_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) -// outgoingGossipingRequestManager.sendSecretShareRequest(KEYBACKUP_SECRET_SSSS_NAME, mapOf(userId to listOf(otherDeviceId ?: "*"))) -// } + if (autoDone) { + state = VerificationTxState.Verified + transport.done(transactionId) {} } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationInfoDone.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationInfoDone.kt index 2986013fca..8cf96d7d65 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationInfoDone.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/VerificationInfoDone.kt @@ -15,12 +15,12 @@ */ package im.vector.matrix.android.internal.crypto.verification -internal interface VerificationInfoDone : VerificationInfo { +import im.vector.matrix.android.api.session.room.model.message.ValidVerificationDone - override fun asValidObject(): ValidVerificationInfoDone? { +internal interface VerificationInfoDone : VerificationInfo { + + override fun asValidObject(): ValidVerificationDone? { val validTransactionId = transactionId?.takeIf { it.isNotEmpty() } ?: return null - return ValidVerificationInfoDone(validTransactionId) + return ValidVerificationDone(validTransactionId) } } - -internal data class ValidVerificationInfoDone(val transactionId: String) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt index 41d8ce7f44..59ee23cc62 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt @@ -187,9 +187,12 @@ internal class DefaultQrCodeVerificationTransaction( // qrCodeData.sharedSecret will be used to send the start request start(otherQrCodeData.sharedSecret) - trust(canTrustOtherUserMasterKey, - toVerifyDeviceIds.distinct(), - eventuallyMarkMyMasterKeyAsTrusted = true) + trust( + canTrustOtherUserMasterKey = canTrustOtherUserMasterKey, + toVerifyDeviceIds = toVerifyDeviceIds.distinct(), + eventuallyMarkMyMasterKeyAsTrusted = true, + autoDone = false + ) } private fun start(remoteSecret: String, onDone: (() -> Unit)? = null) { @@ -199,6 +202,7 @@ internal class DefaultQrCodeVerificationTransaction( throw IllegalStateException("Interactive Key verification already started") } + state = VerificationTxState.Started val startMessage = transport.createStartForQrCode( deviceId, transactionId, @@ -208,7 +212,7 @@ internal class DefaultQrCodeVerificationTransaction( transport.sendToOther( EventType.KEY_VERIFICATION_START, startMessage, - VerificationTxState.Started, + VerificationTxState.WaitingOtherReciprocateConfirm, CancelCode.User, onDone ) @@ -244,6 +248,15 @@ internal class DefaultQrCodeVerificationTransaction( } } + fun onDoneReceived() { + if (state != VerificationTxState.WaitingOtherReciprocateConfirm) { + cancel(CancelCode.UnexpectedMessage) + return + } + state = VerificationTxState.Verified + transport.done(transactionId) {} + } + override fun otherUserScannedMyQrCode() { when (qrCodeData) { is QrCodeData.VerifyingAnotherUser -> { @@ -265,6 +278,6 @@ internal class DefaultQrCodeVerificationTransaction( override fun otherUserDidNotScannedMyQrCode() { // What can I do then? // At least remove the transaction... - state = VerificationTxState.Cancelled(CancelCode.MismatchedKeys, true) + cancel(CancelCode.MismatchedKeys) } } diff --git a/vector/src/main/java/im/vector/riotx/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/riotx/core/di/FragmentModule.kt index 9f3cdba683..c68972cdd4 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/FragmentModule.kt @@ -37,6 +37,7 @@ import im.vector.riotx.features.crypto.verification.cancel.VerificationNotMeFrag import im.vector.riotx.features.crypto.verification.choose.VerificationChooseMethodFragment import im.vector.riotx.features.crypto.verification.conclusion.VerificationConclusionFragment import im.vector.riotx.features.crypto.verification.emoji.VerificationEmojiCodeFragment +import im.vector.riotx.features.crypto.verification.qrconfirmation.VerificationQRWaitingFragment import im.vector.riotx.features.crypto.verification.qrconfirmation.VerificationQrScannedByOtherFragment import im.vector.riotx.features.crypto.verification.request.VerificationRequestFragment import im.vector.riotx.features.grouplist.GroupListFragment @@ -339,6 +340,11 @@ interface FragmentModule { @FragmentKey(VerificationQrScannedByOtherFragment::class) fun bindVerificationQrScannedByOtherFragment(fragment: VerificationQrScannedByOtherFragment): Fragment + @Binds + @IntoMap + @FragmentKey(VerificationQRWaitingFragment::class) + fun bindVerificationQRWaitingFragment(fragment: VerificationQRWaitingFragment): Fragment + @Binds @IntoMap @FragmentKey(VerificationConclusionFragment::class) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheet.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheet.kt index 6b75c0147a..695716d386 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheet.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheet.kt @@ -50,6 +50,7 @@ import im.vector.riotx.features.crypto.verification.cancel.VerificationNotMeFrag import im.vector.riotx.features.crypto.verification.choose.VerificationChooseMethodFragment import im.vector.riotx.features.crypto.verification.conclusion.VerificationConclusionFragment import im.vector.riotx.features.crypto.verification.emoji.VerificationEmojiCodeFragment +import im.vector.riotx.features.crypto.verification.qrconfirmation.VerificationQRWaitingFragment import im.vector.riotx.features.crypto.verification.qrconfirmation.VerificationQrScannedByOtherFragment import im.vector.riotx.features.crypto.verification.request.VerificationRequestFragment import im.vector.riotx.features.home.AvatarRenderer @@ -244,6 +245,13 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() { showFragment(VerificationQrScannedByOtherFragment::class, Bundle()) return@withState } + is VerificationTxState.Started, + is VerificationTxState.WaitingOtherReciprocateConfirm -> { + showFragment(VerificationQRWaitingFragment::class, Bundle().apply { + putParcelable(MvRx.KEY_ARG, VerificationQRWaitingFragment.Args(state.isMe, state.otherUserMxItem?.getBestName() ?: "")) + }) + return@withState + } is VerificationTxState.Verified -> { showFragment(VerificationConclusionFragment::class, Bundle().apply { putParcelable(MvRx.KEY_ARG, VerificationConclusionFragment.Args(true, null, state.isMe)) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt new file mode 100644 index 0000000000..2214774882 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt @@ -0,0 +1,60 @@ +/* + * 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.riotx.features.crypto.verification.qrconfirmation + +import com.airbnb.epoxy.EpoxyController +import im.vector.riotx.R +import im.vector.riotx.core.resources.ColorProvider +import im.vector.riotx.core.resources.StringProvider +import im.vector.riotx.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem +import im.vector.riotx.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem +import im.vector.riotx.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem +import javax.inject.Inject + +class VerificationQRWaitingController @Inject constructor( + private val stringProvider: StringProvider, + private val colorProvider: ColorProvider +) : EpoxyController() { + + private var args: VerificationQRWaitingFragment.Args? = null + + fun update(args: VerificationQRWaitingFragment.Args) { + this.args = args + requestModelBuild() + } + + override fun buildModels() { + val params = args ?: return + + bottomSheetVerificationNoticeItem { + id("notice") + apply { + notice(stringProvider.getString(R.string.qr_code_scanned_verif_waiting_notice)) + } + } + + bottomSheetVerificationBigImageItem { + id("image") + imageRes(R.drawable.ic_shield_trusted) + } + + bottomSheetVerificationWaitingItem { + id("waiting") + title(stringProvider.getString(R.string.qr_code_scanned_verif_waiting, params.otherUserName)) + } + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQRWaitingFragment.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQRWaitingFragment.kt new file mode 100644 index 0000000000..77de3997cb --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQRWaitingFragment.kt @@ -0,0 +1,59 @@ +/* + * 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.riotx.features.crypto.verification.qrconfirmation + +import android.os.Bundle +import android.os.Parcelable +import android.view.View +import com.airbnb.mvrx.MvRx +import im.vector.riotx.R +import im.vector.riotx.core.extensions.cleanup +import im.vector.riotx.core.extensions.configureWith +import im.vector.riotx.core.platform.VectorBaseFragment +import kotlinx.android.parcel.Parcelize +import kotlinx.android.synthetic.main.bottom_sheet_verification_child_fragment.* +import javax.inject.Inject + +class VerificationQRWaitingFragment @Inject constructor( + val controller: VerificationQRWaitingController +) : VectorBaseFragment() { + + @Parcelize + data class Args( + val isMe: Boolean, + val otherUserName: String + ) : Parcelable + + override fun getLayoutResId() = R.layout.bottom_sheet_verification_child_fragment + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupRecyclerView() + (arguments?.getParcelable(MvRx.KEY_ARG) as? Args)?.let { + controller.update(it) + } + } + + override fun onDestroyView() { + bottomSheetVerificationRecyclerView.cleanup() + super.onDestroyView() + } + + private fun setupRecyclerView() { + bottomSheetVerificationRecyclerView.configureWith(controller, hasFixedSize = false, disableItemAnimation = true) + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt index f775ac7941..6271559d31 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt @@ -21,6 +21,7 @@ import im.vector.riotx.R import im.vector.riotx.core.epoxy.dividerItem import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.resources.StringProvider +import im.vector.riotx.features.crypto.verification.VerificationBottomSheetViewState import im.vector.riotx.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.riotx.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import javax.inject.Inject @@ -32,14 +33,26 @@ class VerificationQrScannedByOtherController @Inject constructor( var listener: Listener? = null - init { + private var viewState: VerificationBottomSheetViewState? = null + + fun update(viewState: VerificationBottomSheetViewState) { + this.viewState = viewState requestModelBuild() } override fun buildModels() { + val state = viewState ?: return + bottomSheetVerificationNoticeItem { id("notice") - notice(stringProvider.getString(R.string.qr_code_scanned_by_other_notice)) + apply { + if (state.isMe) { + val name = state.otherUserMxItem?.getBestName() ?: "" + notice(stringProvider.getString(R.string.qr_code_scanned_self_verif_notice, name)) + } else { + notice(stringProvider.getString(R.string.qr_code_scanned_by_other_notice)) + } + } } dividerItem { diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherFragment.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherFragment.kt index 14d294a27a..a8a16f8006 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherFragment.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.crypto.verification.qrconfirmation import android.os.Bundle import android.view.View import com.airbnb.mvrx.parentFragmentViewModel +import com.airbnb.mvrx.withState import im.vector.riotx.R import im.vector.riotx.core.extensions.cleanup import im.vector.riotx.core.extensions.configureWith @@ -37,10 +38,13 @@ class VerificationQrScannedByOtherFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setupRecyclerView() } + override fun invalidate() = withState(sharedViewModel) { state -> + controller.update(state) + } + override fun onDestroyView() { bottomSheetVerificationRecyclerView.cleanup() controller.listener = null diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 928aafbd55..ae2cb7bbbb 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2148,7 +2148,7 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming QR code - Did the other user successfully scan the QR code? + Almost there! Is %s showing the same shield? Yes No diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index a3f57b7716..9ef21170a4 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -94,6 +94,11 @@ The encryption used by this room is not supported %s created and configured the room. + + Almost there! Is the other device showing the same shield? + Almost there! Waiting for confirmation… + Waiting for %s… + Failed to import keys From 68323057aad43872952232bc02db04ad31f8c216 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 9 Apr 2020 16:34:30 +0200 Subject: [PATCH 17/20] Update change log --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 174f4e3a6f..0df276fc2f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ Improvements 🙌: - Cross-Signing | Gossip key backup recovery key (#1200) - Show room encryption status as a bubble tile (#1078) - Cross-Signing | Restore history after recover from passphrase (#1214) + - Cross-Sign | QR code scan confirmation screens design update (#1187) Bugfix 🐛: - Missing avatar/displayname after verification request message (#841) From fccfd00949393b33b8cac2fa52a2518c7d2fa5cc Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 9 Apr 2020 17:04:24 +0200 Subject: [PATCH 18/20] Fix / design update --- .../VerificationQrScannedByOtherController.kt | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt index 6271559d31..c7a086a423 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt @@ -23,6 +23,7 @@ import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.features.crypto.verification.VerificationBottomSheetViewState import im.vector.riotx.features.crypto.verification.epoxy.bottomSheetVerificationActionItem +import im.vector.riotx.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem import im.vector.riotx.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem import javax.inject.Inject @@ -55,23 +56,15 @@ class VerificationQrScannedByOtherController @Inject constructor( } } + bottomSheetVerificationBigImageItem { + id("image") + imageRes(R.drawable.ic_shield_trusted) + } + dividerItem { id("sep0") } - bottomSheetVerificationActionItem { - id("confirm") - title(stringProvider.getString(R.string.qr_code_scanned_by_other_yes)) - titleColor(colorProvider.getColor(R.color.riotx_accent)) - iconRes(R.drawable.ic_check_on) - iconColor(colorProvider.getColor(R.color.riotx_accent)) - listener { listener?.onUserConfirmsQrCodeScanned() } - } - - dividerItem { - id("sep1") - } - bottomSheetVerificationActionItem { id("deny") title(stringProvider.getString(R.string.qr_code_scanned_by_other_no)) @@ -80,6 +73,19 @@ class VerificationQrScannedByOtherController @Inject constructor( iconColor(colorProvider.getColor(R.color.vector_error_color)) listener { listener?.onUserDeniesQrCodeScanned() } } + + dividerItem { + id("sep1") + } + + bottomSheetVerificationActionItem { + id("confirm") + title(stringProvider.getString(R.string.qr_code_scanned_by_other_yes)) + titleColor(colorProvider.getColor(R.color.riotx_accent)) + iconRes(R.drawable.ic_check_on) + iconColor(colorProvider.getColor(R.color.riotx_accent)) + listener { listener?.onUserConfirmsQrCodeScanned() } + } } interface Listener { From 943ba3bebdce0c86ff3579960c361fc9e0cc3972 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 10 Apr 2020 13:14:12 +0200 Subject: [PATCH 19/20] Fix / string bad argument number - lint --- .../VerificationQrScannedByOtherController.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt index c7a086a423..dd1d3d0f90 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt @@ -48,10 +48,10 @@ class VerificationQrScannedByOtherController @Inject constructor( id("notice") apply { if (state.isMe) { - val name = state.otherUserMxItem?.getBestName() ?: "" - notice(stringProvider.getString(R.string.qr_code_scanned_self_verif_notice, name)) + notice(stringProvider.getString(R.string.qr_code_scanned_self_verif_notice)) } else { - notice(stringProvider.getString(R.string.qr_code_scanned_by_other_notice)) + val name = state.otherUserMxItem?.getBestName() ?: "" + notice(stringProvider.getString(R.string.qr_code_scanned_by_other_notice, name)) } } } From 9cfb83f0d2cff846e78868c1b6908b2a1766348c Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 10 Apr 2020 14:31:03 +0200 Subject: [PATCH 20/20] Remove outdated translation --- vector/src/main/res/values-eu/strings.xml | 1 - vector/src/main/res/values-fr/strings.xml | 1 - vector/src/main/res/values-hu/strings.xml | 1 - vector/src/main/res/values-it/strings.xml | 1 - vector/src/main/res/values-sq/strings.xml | 1 - vector/src/main/res/values-zh-rTW/strings.xml | 1 - 6 files changed, 6 deletions(-) diff --git a/vector/src/main/res/values-eu/strings.xml b/vector/src/main/res/values-eu/strings.xml index 86fb1e0e12..dd8ead5f27 100644 --- a/vector/src/main/res/values-eu/strings.xml +++ b/vector/src/main/res/values-eu/strings.xml @@ -2166,7 +2166,6 @@ Abisua: Fitxategi hau ezabatu daiteke aplikazioa desinstalatzen bada. QR kodea - Beste erabiltzaileak QR kodea ongi eskaneatu du\? Bai Ez diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml index 341a247d52..76e2a0d0a7 100644 --- a/vector/src/main/res/values-fr/strings.xml +++ b/vector/src/main/res/values-fr/strings.xml @@ -2174,7 +2174,6 @@ Si vous n’avez pas configuré de nouvelle méthode de récupération, un attaq Code QR - L’autre utilisateur a-t-il bien scanné le code QR \? Oui Non diff --git a/vector/src/main/res/values-hu/strings.xml b/vector/src/main/res/values-hu/strings.xml index 64eee79075..c4dde2e079 100644 --- a/vector/src/main/res/values-hu/strings.xml +++ b/vector/src/main/res/values-hu/strings.xml @@ -2169,7 +2169,6 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró QR kód - A másik felhasználó sikeresen beolvasta a QR kódot\? Igen Nem diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml index 4d1ac8edaf..92b235c5dd 100644 --- a/vector/src/main/res/values-it/strings.xml +++ b/vector/src/main/res/values-it/strings.xml @@ -2219,7 +2219,6 @@ Codice QR - L\'altro utente ha scansionato correttamente il codice QR\? No diff --git a/vector/src/main/res/values-sq/strings.xml b/vector/src/main/res/values-sq/strings.xml index 7ff5253530..96e0e1201a 100644 --- a/vector/src/main/res/values-sq/strings.xml +++ b/vector/src/main/res/values-sq/strings.xml @@ -2129,7 +2129,6 @@ Që të garantoni se s’ju shpëton gjë, thjesht mbajeni të aktivizuar mekani Gatit CrossSigning Zeroji Kyçet - A e skanoi me sukses përdoruesi tjetër kodin QR\? Jo Humbi lidhja me shërbyesin diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml index 8078ca8efa..111ee26b36 100644 --- a/vector/src/main/res/values-zh-rTW/strings.xml +++ b/vector/src/main/res/values-zh-rTW/strings.xml @@ -2119,7 +2119,6 @@ Matrix 中的消息可見度類似于電子郵件。我們忘記您的郵件意 QR code - 其他使用者是否掃苗 QR code 成功?