From 041fcef1db267de5f8dfcf954fb4f043d38238c0 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 7 Dec 2022 10:30:47 +0100 Subject: [PATCH 01/20] Adding changelog entry --- changelog.d/7733.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7733.bugfix diff --git a/changelog.d/7733.bugfix b/changelog.d/7733.bugfix new file mode 100644 index 0000000000..9de3759f1a --- /dev/null +++ b/changelog.d/7733.bugfix @@ -0,0 +1 @@ +[Session manager] Sessions without encryption support should not prompt to verify From f014866d063a6c7d1df769c4c74cbd6aa7d916c9 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 7 Dec 2022 14:34:45 +0100 Subject: [PATCH 02/20] Handling the case where device has no CryptoDeviceInfo --- .../src/main/res/values/strings.xml | 2 + .../app/core/ui/views/ShieldImageView.kt | 28 ++++++++------ .../settings/devices/DevicesViewModel.kt | 2 +- .../settings/devices/v2/DeviceFullInfo.kt | 2 +- .../devices/v2/list/SessionInfoView.kt | 11 +++++- .../v2/overview/SessionOverviewFragment.kt | 37 +++++++++++-------- ...GetEncryptionTrustLevelForDeviceUseCase.kt | 10 +++-- ...ncryptionTrustLevelForDeviceUseCaseTest.kt | 15 ++++++++ 8 files changed, 75 insertions(+), 32 deletions(-) diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index 609cdac233..b10d11d048 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -3305,6 +3305,7 @@ Verify your current session for enhanced secure messaging. Verify or sign out from this session for best security and reliability. Verify your current session to reveal this session\'s verification status. + This session doesn\'t support encryption and thus can\'t be verified. Verify Session View Details View All (%1$d) @@ -3397,6 +3398,7 @@ Verified sessions have logged in with your credentials and then been verified, either using your secure passphrase or by cross-verifying.\n\nThis means they hold encryption keys for your previous messages, and confirm to other users you are communicating with that these sessions are really you. Verified sessions are anywhere you are using this account after entering your passphrase or confirming your identity with another verified session.\n\nThis means that you have all the keys needed to unlock your encrypted messages and confirm to other users that you trust this session. + This session doesn\'t support encryption, so it can\'t be verified.\n\nYou won\'t be able to participate in rooms where encryption is enabled when using this session.\n\nFor best security and privacy, it is recommended to use Matrix clients that support encryption. Renaming sessions Other users in direct messages and rooms that you join are able to view a full list of your sessions.\n\nThis provides them with confidence that they are really speaking to you, but it also means they can see the session name you enter here. Enable new session manager diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt index 0570bbe4d7..34714d97d0 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt @@ -40,20 +40,26 @@ class ShieldImageView @JvmOverloads constructor( /** * Renders device shield with the support of unknown shields instead of black shields which is used for rooms. - * @param roomEncryptionTrustLevel trust level that is usally calculated with [im.vector.app.features.settings.devices.TrustUtils.shieldForTrust] + * @param roomEncryptionTrustLevel trust level that is usually calculated with [im.vector.app.features.settings.devices.TrustUtils.shieldForTrust] * @param borderLess if true then the shield icon with border around is used */ fun renderDeviceShield(roomEncryptionTrustLevel: RoomEncryptionTrustLevel?, borderLess: Boolean = false) { - isVisible = roomEncryptionTrustLevel != null - - if (roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Default) { - contentDescription = context.getString(R.string.a11y_trust_level_default) - setImageResource( - if (borderLess) R.drawable.ic_shield_unknown_no_border - else R.drawable.ic_shield_unknown - ) - } else { - render(roomEncryptionTrustLevel, borderLess) + when (roomEncryptionTrustLevel) { + null -> { + contentDescription = context.getString(R.string.a11y_trust_level_warning) + setImageResource( + if (borderLess) R.drawable.ic_shield_warning_no_border + else R.drawable.ic_shield_warning + ) + } + RoomEncryptionTrustLevel.Default -> { + contentDescription = context.getString(R.string.a11y_trust_level_default) + setImageResource( + if (borderLess) R.drawable.ic_shield_unknown_no_border + else R.drawable.ic_shield_unknown + ) + } + else -> render(roomEncryptionTrustLevel, borderLess) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 67b41ea5aa..e779948b41 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -88,7 +88,7 @@ data class DevicesViewState( data class DeviceFullInfo( val deviceInfo: DeviceInfo, val cryptoDeviceInfo: CryptoDeviceInfo?, - val trustLevelForShield: RoomEncryptionTrustLevel, + val trustLevelForShield: RoomEncryptionTrustLevel?, val isInactive: Boolean, ) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/DeviceFullInfo.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/DeviceFullInfo.kt index 4864c41394..186a6ebe69 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/DeviceFullInfo.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/DeviceFullInfo.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel data class DeviceFullInfo( val deviceInfo: DeviceInfo, val cryptoDeviceInfo: CryptoDeviceInfo?, - val roomEncryptionTrustLevel: RoomEncryptionTrustLevel, + val roomEncryptionTrustLevel: RoomEncryptionTrustLevel?, val isInactive: Boolean, val isCurrentDevice: Boolean, val deviceExtendedInfo: DeviceExtendedInfo, diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt index 7727cee4fa..eecec72b0a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/SessionInfoView.kt @@ -85,13 +85,14 @@ class SessionInfoView @JvmOverloads constructor( } private fun renderVerificationStatus( - encryptionTrustLevel: RoomEncryptionTrustLevel, + encryptionTrustLevel: RoomEncryptionTrustLevel?, isCurrentSession: Boolean, hasLearnMoreLink: Boolean, isVerifyButtonVisible: Boolean, ) { views.sessionInfoVerificationStatusImageView.renderDeviceShield(encryptionTrustLevel) when { + encryptionTrustLevel == null -> renderCrossSigningEncryptionNotSupported() encryptionTrustLevel == RoomEncryptionTrustLevel.Trusted -> renderCrossSigningVerified(isCurrentSession) encryptionTrustLevel == RoomEncryptionTrustLevel.Default && !isCurrentSession -> renderCrossSigningUnknown() else -> renderCrossSigningUnverified(isCurrentSession, isVerifyButtonVisible) @@ -149,6 +150,14 @@ class SessionInfoView @JvmOverloads constructor( views.sessionInfoVerifySessionButton.isVisible = false } + private fun renderCrossSigningEncryptionNotSupported() { + views.sessionInfoVerificationStatusTextView.text = context.getString(R.string.device_manager_verification_status_unverified) + views.sessionInfoVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, R.attr.colorError)) + views.sessionInfoVerificationStatusDetailTextView.text = + context.getString(R.string.device_manager_verification_status_detail_session_encryption_not_supported) + views.sessionInfoVerifySessionButton.isVisible = false + } + private fun renderDeviceInfo(sessionName: String, deviceType: DeviceType, stringProvider: StringProvider) { setDeviceTypeIconUseCase.execute(deviceType, views.sessionInfoDeviceTypeImageView, stringProvider) views.sessionInfoNameTextView.text = sessionName diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index be60b3b805..6fbd2f1fef 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -229,7 +229,7 @@ class SessionOverviewFragment : ) views.sessionOverviewInfo.render(infoViewState, dateFormatter, drawableProvider, colorProvider, stringProvider) views.sessionOverviewInfo.onLearnMoreClickListener = { - showLearnMoreInfoVerificationStatus(deviceInfo.roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Trusted) + showLearnMoreInfoVerificationStatus(deviceInfo.roomEncryptionTrustLevel) } } else { views.sessionOverviewInfo.isVisible = false @@ -293,21 +293,28 @@ class SessionOverviewFragment : } } - private fun showLearnMoreInfoVerificationStatus(isVerified: Boolean) { - val titleResId = if (isVerified) { - R.string.device_manager_verification_status_verified - } else { - R.string.device_manager_verification_status_unverified + private fun showLearnMoreInfoVerificationStatus(roomEncryptionTrustLevel: RoomEncryptionTrustLevel?) { + val args = when(roomEncryptionTrustLevel) { + null -> { + // encryption not supported + SessionLearnMoreBottomSheet.Args( + title = getString(R.string.device_manager_verification_status_unverified), + description = getString(R.string.device_manager_learn_more_sessions_encryption_not_supported), + ) + } + RoomEncryptionTrustLevel.Trusted -> { + SessionLearnMoreBottomSheet.Args( + title = getString(R.string.device_manager_verification_status_verified), + description = getString(R.string.device_manager_learn_more_sessions_verified_description), + ) + } + else -> { + SessionLearnMoreBottomSheet.Args( + title = getString(R.string.device_manager_verification_status_unverified), + description = getString(R.string.device_manager_learn_more_sessions_unverified), + ) + } } - val descriptionResId = if (isVerified) { - R.string.device_manager_learn_more_sessions_verified_description - } else { - R.string.device_manager_learn_more_sessions_unverified - } - val args = SessionLearnMoreBottomSheet.Args( - title = getString(titleResId), - description = getString(descriptionResId), - ) SessionLearnMoreBottomSheet.show(childFragmentManager, args) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt index ba9a380ade..31a7e93d04 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt @@ -25,11 +25,15 @@ class GetEncryptionTrustLevelForDeviceUseCase @Inject constructor( private val getEncryptionTrustLevelForOtherDeviceUseCase: GetEncryptionTrustLevelForOtherDeviceUseCase, ) { - fun execute(currentSessionCrossSigningInfo: CurrentSessionCrossSigningInfo, cryptoDeviceInfo: CryptoDeviceInfo?): RoomEncryptionTrustLevel { + fun execute(currentSessionCrossSigningInfo: CurrentSessionCrossSigningInfo, cryptoDeviceInfo: CryptoDeviceInfo?): RoomEncryptionTrustLevel? { + if(cryptoDeviceInfo == null) { + return null + } + val legacyMode = !currentSessionCrossSigningInfo.isCrossSigningInitialized val trustMSK = currentSessionCrossSigningInfo.isCrossSigningVerified - val isCurrentDevice = !cryptoDeviceInfo?.deviceId.isNullOrEmpty() && cryptoDeviceInfo?.deviceId == currentSessionCrossSigningInfo.deviceId - val deviceTrustLevel = cryptoDeviceInfo?.trustLevel + val isCurrentDevice = !cryptoDeviceInfo.deviceId.isNullOrEmpty() && cryptoDeviceInfo.deviceId == currentSessionCrossSigningInfo.deviceId + val deviceTrustLevel = cryptoDeviceInfo.trustLevel return when { isCurrentDevice -> getEncryptionTrustLevelForCurrentDeviceUseCase.execute(trustMSK, legacyMode) diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCaseTest.kt index 1b39fe5f73..fd10ee1083 100644 --- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCaseTest.kt @@ -19,6 +19,7 @@ package im.vector.app.features.settings.devices.v2.verification import io.mockk.every import io.mockk.mockk import io.mockk.verify +import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeEqualTo import org.junit.Test import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel @@ -89,6 +90,20 @@ class GetEncryptionTrustLevelForDeviceUseCaseTest { } } + @Test + fun `given no crypto device info when computing trust level then result is null`() { + val currentSessionCrossSigningInfo = givenCurrentSessionCrossSigningInfo( + deviceId = A_DEVICE_ID, + isCrossSigningInitialized = true, + isCrossSigningVerified = false + ) + val cryptoDeviceInfo = null + + val result = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoDeviceInfo) + + result shouldBe null + } + private fun givenCurrentSessionCrossSigningInfo( deviceId: String, isCrossSigningInitialized: Boolean, From 88f743988064b51c1562b8c9291032f2e83639a8 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 7 Dec 2022 15:52:56 +0100 Subject: [PATCH 03/20] Updating comment to clarify intention --- .../app/features/home/UnknownDeviceDetectorSharedViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt index 21c7bd6ea1..347c16653d 100644 --- a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt @@ -104,7 +104,7 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor( // Timber.v("## Detector trigger canCrossSign ${pInfo.get().selfSigned != null}") infoList .filter { info -> - // filter verified session, by checking the crypto device info + // filter out verified sessions or those which do not support encryption (i.e. without crypto info) cryptoList.firstOrNull { info.deviceId == it.deviceId }?.isVerified?.not().orFalse() } // filter out ignored devices From 23c2682f8d4e85466a90352f99bb9ad2b40630c0 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 7 Dec 2022 16:39:51 +0100 Subject: [PATCH 04/20] Fixing code style issues --- .../settings/devices/v2/overview/SessionOverviewFragment.kt | 2 +- .../v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index 6fbd2f1fef..f3df0cced0 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -294,7 +294,7 @@ class SessionOverviewFragment : } private fun showLearnMoreInfoVerificationStatus(roomEncryptionTrustLevel: RoomEncryptionTrustLevel?) { - val args = when(roomEncryptionTrustLevel) { + val args = when (roomEncryptionTrustLevel) { null -> { // encryption not supported SessionLearnMoreBottomSheet.Args( diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt index 31a7e93d04..268ae86601 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/verification/GetEncryptionTrustLevelForDeviceUseCase.kt @@ -26,7 +26,7 @@ class GetEncryptionTrustLevelForDeviceUseCase @Inject constructor( ) { fun execute(currentSessionCrossSigningInfo: CurrentSessionCrossSigningInfo, cryptoDeviceInfo: CryptoDeviceInfo?): RoomEncryptionTrustLevel? { - if(cryptoDeviceInfo == null) { + if (cryptoDeviceInfo == null) { return null } From a5ab1b4a8bdf10bb61a0c2966c63dc6be8837283 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Dec 2022 10:34:08 +0100 Subject: [PATCH 05/20] Fix crash `kotlin.UninitializedPropertyAccessException: lateinit property avatarRenderer has not been initialized`. AvatarRenderer is not used here. --- .../im/vector/app/features/userdirectory/InviteByEmailItem.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/InviteByEmailItem.kt b/vector/src/main/java/im/vector/app/features/userdirectory/InviteByEmailItem.kt index eaeec35791..da1d76e86a 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/InviteByEmailItem.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/InviteByEmailItem.kt @@ -25,12 +25,10 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.features.home.AvatarRenderer @EpoxyModelClass abstract class InviteByEmailItem : VectorEpoxyModel(R.layout.item_invite_by_mail) { - @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute lateinit var foundItem: ThreePidUser @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var clickListener: ClickListener? = null @EpoxyAttribute var selected: Boolean = false From 7034d822594a5d7417444c7d613893565e5c6ae9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Dec 2022 10:36:29 +0100 Subject: [PATCH 06/20] changelog --- changelog.d/7744.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7744.bugfix diff --git a/changelog.d/7744.bugfix b/changelog.d/7744.bugfix new file mode 100644 index 0000000000..7ed82a9c1c --- /dev/null +++ b/changelog.d/7744.bugfix @@ -0,0 +1 @@ +Fix crash when inviting by email. From b49045ff15044202a4ac104c39d2ebbf6eae53df Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 8 Dec 2022 10:37:00 +0100 Subject: [PATCH 07/20] Adding changelog entry --- changelog.d/7743.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7743.bugfix diff --git a/changelog.d/7743.bugfix b/changelog.d/7743.bugfix new file mode 100644 index 0000000000..867c12a3c3 --- /dev/null +++ b/changelog.d/7743.bugfix @@ -0,0 +1 @@ +Verification request is not showing when verify session popup is displayed From b25f185d63b5de9e1cb5523650e7aa7b5623cdc5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Dec 2022 10:48:17 +0100 Subject: [PATCH 08/20] Try to fix issue about danger file not found. --- .github/workflows/danger.yml | 2 +- .github/workflows/quality.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index e5226d0723..8752f339bd 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -13,7 +13,7 @@ jobs: - name: Danger uses: danger/danger-js@11.2.0 with: - args: "--dangerfile tools/danger/dangerfile.js" + args: "--dangerfile ./tools/danger/dangerfile.js" env: DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} # Fallback for forks diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 57dd5a6a45..fae8d97688 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -68,7 +68,7 @@ jobs: if: always() uses: danger/danger-js@11.2.0 with: - args: "--dangerfile tools/danger/dangerfile-lint.js" + args: "--dangerfile ./tools/danger/dangerfile-lint.js" env: DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} # Fallback for forks From df55c841670ff0d13cf911bd80ce161479c1b33a Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 8 Dec 2022 14:00:35 +0100 Subject: [PATCH 09/20] Raise priority of incoming verification request alert + cancel existing verification alerts --- .../IncomingVerificationRequestHandler.kt | 26 ++++++------ .../vector/app/features/home/HomeActivity.kt | 40 ++++++++++++------- .../app/features/home/HomeDetailFragment.kt | 2 +- .../features/home/NewHomeDetailFragment.kt | 2 +- .../app/features/popup/PopupAlertManager.kt | 8 +++- .../vector/app/features/popup/VectorAlert.kt | 2 +- .../features/popup/VerificationVectorAlert.kt | 1 + 7 files changed, 50 insertions(+), 31 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt index 3a5c7e7eb8..c749e9578e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt @@ -72,10 +72,11 @@ class IncomingVerificationRequestHandler @Inject constructor( val user = session.getUserOrDefault(tx.otherUserId).toMatrixItem() val name = user.getBestName() val alert = VerificationVectorAlert( - uid, - context.getString(R.string.sas_incoming_request_notif_title), - context.getString(R.string.sas_incoming_request_notif_content, name), - R.drawable.ic_shield_black, + uid = uid, + title = context.getString(R.string.sas_incoming_request_notif_title), + description = context.getString(R.string.sas_incoming_request_notif_content, name), + iconId = R.drawable.ic_shield_black, + priority = PopupAlertManager.INCOMING_VERIFICATION_REQUEST_PRIORITY, shouldBeDisplayedIn = { activity -> if (activity is VectorBaseActivity<*>) { // TODO a bit too ugly :/ @@ -85,7 +86,7 @@ class IncomingVerificationRequestHandler @Inject constructor( } } ?: true } else true - } + }, ) .apply { viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer.get()) @@ -130,8 +131,8 @@ class IncomingVerificationRequestHandler @Inject constructor( // if not this request will be underneath and not visible by the user... // it will re-appear later if (pr.otherUserId == session?.myUserId) { - // XXX this is a bit hard coded :/ - popupAlertManager.cancelAlert("review_login") + popupAlertManager.cancelAlert(PopupAlertManager.REVIEW_LOGIN_UID) + popupAlertManager.cancelAlert(PopupAlertManager.VERIFY_SESSION_UID) } val user = session.getUserOrDefault(pr.otherUserId).toMatrixItem() val name = user.getBestName() @@ -142,17 +143,18 @@ class IncomingVerificationRequestHandler @Inject constructor( } val alert = VerificationVectorAlert( - uniqueIdForVerificationRequest(pr), - context.getString(R.string.sas_incoming_request_notif_title), - description, - R.drawable.ic_shield_black, + uid = uniqueIdForVerificationRequest(pr), + title = context.getString(R.string.sas_incoming_request_notif_title), + description = description, + iconId = R.drawable.ic_shield_black, + priority = PopupAlertManager.INCOMING_VERIFICATION_REQUEST_PRIORITY, shouldBeDisplayedIn = { activity -> if (activity is RoomDetailActivity) { activity.intent?.extras?.getParcelableCompat(RoomDetailActivity.EXTRA_ROOM_DETAIL_ARGS)?.let { it.roomId != pr.roomId } ?: true } else true - } + }, ) .apply { viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer.get()) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 2a3d8d094c..e08ed6db46 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -437,9 +437,10 @@ class HomeActivity : private fun handleAskPasswordToInitCrossSigning(events: HomeActivityViewEvents.AskPasswordToInitCrossSigning) { // We need to ask promptSecurityEvent( - events.userItem, - R.string.upgrade_security, - R.string.security_prompt_text + uid = PopupAlertManager.UPGRADE_SECURITY_UID, + userItem = events.userItem, + titleRes = R.string.upgrade_security, + descRes = R.string.security_prompt_text, ) { it.navigator.upgradeSessionSecurity(it, true) } @@ -448,9 +449,10 @@ class HomeActivity : private fun handleCrossSigningInvalidated(event: HomeActivityViewEvents.OnCrossSignedInvalidated) { // We need to ask promptSecurityEvent( - event.userItem, - R.string.crosssigning_verify_this_session, - R.string.confirm_your_identity + uid = PopupAlertManager.VERIFY_SESSION_UID, + userItem = event.userItem, + titleRes = R.string.crosssigning_verify_this_session, + descRes = R.string.confirm_your_identity, ) { it.navigator.waitSessionVerification(it) } @@ -459,9 +461,10 @@ class HomeActivity : private fun handleOnNewSession(event: HomeActivityViewEvents.CurrentSessionNotVerified) { // We need to ask promptSecurityEvent( - event.userItem, - R.string.crosssigning_verify_this_session, - R.string.confirm_your_identity + uid = PopupAlertManager.VERIFY_SESSION_UID, + userItem = event.userItem, + titleRes = R.string.crosssigning_verify_this_session, + descRes = R.string.confirm_your_identity, ) { if (event.waitForIncomingRequest) { it.navigator.waitSessionVerification(it) @@ -474,9 +477,10 @@ class HomeActivity : private fun handleCantVerify(event: HomeActivityViewEvents.CurrentSessionCannotBeVerified) { // We need to ask promptSecurityEvent( - event.userItem, - R.string.crosssigning_cannot_verify_this_session, - R.string.crosssigning_cannot_verify_this_session_desc + uid = PopupAlertManager.UPGRADE_SECURITY_UID, + userItem = event.userItem, + titleRes = R.string.crosssigning_cannot_verify_this_session, + descRes = R.string.crosssigning_cannot_verify_this_session_desc, ) { it.navigator.open4SSetup(it, SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET) } @@ -485,7 +489,7 @@ class HomeActivity : private fun handlePromptToEnablePush() { popupAlertManager.postVectorAlert( DefaultVectorAlert( - uid = "enablePush", + uid = PopupAlertManager.ENABLE_PUSH_UID, title = getString(R.string.alert_push_are_disabled_title), description = getString(R.string.alert_push_are_disabled_description), iconId = R.drawable.ic_room_actions_notifications_mutes, @@ -518,10 +522,16 @@ class HomeActivity : ) } - private fun promptSecurityEvent(userItem: MatrixItem.UserItem, titleRes: Int, descRes: Int, action: ((VectorBaseActivity<*>) -> Unit)) { + private fun promptSecurityEvent( + uid: String, + userItem: MatrixItem.UserItem, + titleRes: Int, + descRes: Int, + action: ((VectorBaseActivity<*>) -> Unit), + ) { popupAlertManager.postVectorAlert( VerificationVectorAlert( - uid = "upgradeSecurity", + uid = uid, title = getString(titleRes), description = getString(descRes), iconId = R.drawable.ic_shield_warning diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index 69abeed424..d310f574dd 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -156,7 +156,7 @@ class HomeDetailFragment : unknownDeviceDetectorSharedViewModel.onEach { state -> state.unknownSessions.invoke()?.let { unknownDevices -> if (unknownDevices.firstOrNull()?.currentSessionTrust == true) { - val uid = "review_login" + val uid = PopupAlertManager.REVIEW_LOGIN_UID alertManager.cancelAlert(uid) val olderUnverified = unknownDevices.filter { !it.isNew } val newest = unknownDevices.firstOrNull { it.isNew }?.deviceInfo diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index ccd5a7e84b..3189c2b99e 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -160,7 +160,7 @@ class NewHomeDetailFragment : unknownDeviceDetectorSharedViewModel.onEach { state -> state.unknownSessions.invoke()?.let { unknownDevices -> if (unknownDevices.firstOrNull()?.currentSessionTrust == true) { - val uid = "review_login" + val uid = PopupAlertManager.REVIEW_LOGIN_UID alertManager.cancelAlert(uid) val olderUnverified = unknownDevices.filter { !it.isNew } val newest = unknownDevices.firstOrNull { it.isNew }?.deviceInfo diff --git a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt index b1327f0caf..e0310b340e 100644 --- a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt +++ b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt @@ -50,6 +50,12 @@ class PopupAlertManager @Inject constructor( companion object { const val INCOMING_CALL_PRIORITY = Int.MAX_VALUE + const val INCOMING_VERIFICATION_REQUEST_PRIORITY = 1 + const val DEFAULT_PRIORITY = 0 + const val REVIEW_LOGIN_UID = "review_login" + const val UPGRADE_SECURITY_UID = "upgrade_security" + const val VERIFY_SESSION_UID = "verify_session" + const val ENABLE_PUSH_UID = "enable_push" } private var weakCurrentActivity: WeakReference? = null @@ -145,7 +151,7 @@ class PopupAlertManager @Inject constructor( private fun displayNextIfPossible() { val currentActivity = weakCurrentActivity?.get() - if (Alerter.isShowing || currentActivity == null || currentActivity.isDestroyed) { + if (currentActivity == null || currentActivity.isDestroyed) { // will retry later return } diff --git a/vector/src/main/java/im/vector/app/features/popup/VectorAlert.kt b/vector/src/main/java/im/vector/app/features/popup/VectorAlert.kt index ffdba8e04d..1597d927d8 100644 --- a/vector/src/main/java/im/vector/app/features/popup/VectorAlert.kt +++ b/vector/src/main/java/im/vector/app/features/popup/VectorAlert.kt @@ -98,7 +98,7 @@ open class DefaultVectorAlert( override val dismissOnClick: Boolean = true - override val priority: Int = 0 + override val priority: Int = PopupAlertManager.DEFAULT_PRIORITY override val isLight: Boolean = false diff --git a/vector/src/main/java/im/vector/app/features/popup/VerificationVectorAlert.kt b/vector/src/main/java/im/vector/app/features/popup/VerificationVectorAlert.kt index c2ecbe04b3..818659872f 100644 --- a/vector/src/main/java/im/vector/app/features/popup/VerificationVectorAlert.kt +++ b/vector/src/main/java/im/vector/app/features/popup/VerificationVectorAlert.kt @@ -30,6 +30,7 @@ class VerificationVectorAlert( title: String, override val description: String, @DrawableRes override val iconId: Int?, + override val priority: Int = PopupAlertManager.DEFAULT_PRIORITY, /** * Alert are displayed by default, but let this lambda return false to prevent displaying. */ From 73fd93148ad012dc0f4ab60fd1b892c1a51e21d0 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 2 Dec 2022 18:14:58 +0000 Subject: [PATCH 10/20] Download device keys for self prior to verification checks Fixes https://github.com/vector-im/element-android/issues/7676 --- .../org/matrix/android/sdk/api/rendezvous/Rendezvous.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt index f724ac4b62..d421f8f994 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt @@ -35,7 +35,10 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_S import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.util.MatrixJsonParser +import org.matrix.android.sdk.api.util.awaitCallback import timber.log.Timber /** @@ -147,6 +150,9 @@ class Rendezvous( val deviceKey = crypto.getMyDevice().fingerprint() send(Payload(PayloadType.PROGRESS, outcome = Outcome.SUCCESS, deviceId = deviceId, deviceKey = deviceKey)) + // explicitly download keys for ourself rather than wait for initial sync to complete + awaitCallback> { crypto.downloadKeys(listOf(userId), false, it) } + // await confirmation of verification val verificationResponse = receive() if (verificationResponse?.outcome == Outcome.VERIFIED) { From d0b2c0693de63ff69195c6bb3fac756725e8ac02 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 2 Dec 2022 18:19:02 +0000 Subject: [PATCH 11/20] Changelog --- changelog.d/7699.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7699.bugfix diff --git a/changelog.d/7699.bugfix b/changelog.d/7699.bugfix new file mode 100644 index 0000000000..30a4b8e9fa --- /dev/null +++ b/changelog.d/7699.bugfix @@ -0,0 +1 @@ +Fix E2EE set up failure whilst signing in using QR code From 3a2a916c2f17609fdfba82df08f3160e2685ec68 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Tue, 6 Dec 2022 11:34:25 +0000 Subject: [PATCH 12/20] Clarify comment --- .../java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt index d421f8f994..3364e900c6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt @@ -150,7 +150,7 @@ class Rendezvous( val deviceKey = crypto.getMyDevice().fingerprint() send(Payload(PayloadType.PROGRESS, outcome = Outcome.SUCCESS, deviceId = deviceId, deviceKey = deviceKey)) - // explicitly download keys for ourself rather than wait for initial sync to complete + // explicitly download keys for ourself rather than racing with initial sync which might not complete in time awaitCallback> { crypto.downloadKeys(listOf(userId), false, it) } // await confirmation of verification From 7bbd91f2a93adcd9ec73aea618912dda17876236 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 7 Dec 2022 15:09:43 +0000 Subject: [PATCH 13/20] Handle error whilst download key for self --- .../org/matrix/android/sdk/api/rendezvous/Rendezvous.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt index 3364e900c6..e5b2d6bf12 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt @@ -150,8 +150,13 @@ class Rendezvous( val deviceKey = crypto.getMyDevice().fingerprint() send(Payload(PayloadType.PROGRESS, outcome = Outcome.SUCCESS, deviceId = deviceId, deviceKey = deviceKey)) - // explicitly download keys for ourself rather than racing with initial sync which might not complete in time - awaitCallback> { crypto.downloadKeys(listOf(userId), false, it) } + try { + // explicitly download keys for ourself rather than racing with initial sync which might not complete in time + awaitCallback> { crypto.downloadKeys(listOf(userId), false, it) } + } catch (e: Throwable) { + // log as warning and continue as initial sync might still complete + Timber.tag(TAG).w(e, "Failed to download keys for self") + } // await confirmation of verification val verificationResponse = receive() From 63bde230a399bc24e6f33e1ab7254024170c7239 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 8 Dec 2022 14:40:17 +0100 Subject: [PATCH 14/20] Cancel verification alerts when adding the incoming request alert and when starting the process --- .../IncomingVerificationRequestHandler.kt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt index c749e9578e..0f8f5c633e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/IncomingVerificationRequestHandler.kt @@ -128,12 +128,9 @@ class IncomingVerificationRequestHandler @Inject constructor( // For incoming request we should prompt (if not in activity where this request apply) if (pr.isIncoming) { // if it's a self verification for my devices, we can discard the review login alert - // if not this request will be underneath and not visible by the user... + // if not, this request will be underneath and not visible by the user... // it will re-appear later - if (pr.otherUserId == session?.myUserId) { - popupAlertManager.cancelAlert(PopupAlertManager.REVIEW_LOGIN_UID) - popupAlertManager.cancelAlert(PopupAlertManager.VERIFY_SESSION_UID) - } + cancelAnyVerifySessionAlerts(pr) val user = session.getUserOrDefault(pr.otherUserId).toMatrixItem() val name = user.getBestName() val description = if (name == pr.otherUserId) { @@ -159,6 +156,7 @@ class IncomingVerificationRequestHandler @Inject constructor( .apply { viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer.get()) contentAction = Runnable { + cancelAnyVerifySessionAlerts(pr) (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { val roomId = pr.roomId if (roomId.isNullOrBlank()) { @@ -188,6 +186,13 @@ class IncomingVerificationRequestHandler @Inject constructor( } } + private fun cancelAnyVerifySessionAlerts(pr: PendingVerificationRequest) { + if (pr.otherUserId == session?.myUserId) { + popupAlertManager.cancelAlert(PopupAlertManager.REVIEW_LOGIN_UID) + popupAlertManager.cancelAlert(PopupAlertManager.VERIFY_SESSION_UID) + } + } + override fun verificationRequestUpdated(pr: PendingVerificationRequest) { // If an incoming request is readied (by another device?) we should discard the alert if (pr.isIncoming && (pr.isReady || pr.handledByOtherSession || pr.cancelConclusion != null)) { From 220b1d86c03bc9c68ad77bdbd9d9cba426fe9366 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 8 Dec 2022 17:41:29 +0100 Subject: [PATCH 15/20] Reverting usage of some stable fields whereas related MSCs have not landed into the specs yet --- .../room/location/StartLiveLocationShareTask.kt | 2 +- .../session/room/location/StopLiveLocationShareTask.kt | 2 +- .../session/room/send/LocalEchoEventFactory.kt | 10 +++++----- .../room/aggregation/poll/PollEventsTestData.kt | 6 +++--- .../DefaultGetActiveBeaconInfoForUserTaskTest.kt | 2 +- .../location/DefaultStartLiveLocationShareTaskTest.kt | 2 +- .../location/DefaultStopLiveLocationShareTaskTest.kt | 2 +- .../LiveLocationShareRedactionEventProcessorTest.kt | 2 +- .../vector/app/test/fakes/FakeCreatePollViewStates.kt | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt index 13753115ac..dd409fe3a7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt @@ -46,7 +46,7 @@ internal class DefaultStartLiveLocationShareTask @Inject constructor( isLive = true, unstableTimestampMillis = clock.epochMillis() ).toContent() - val eventType = EventType.STATE_ROOM_BEACON_INFO.stable + val eventType = EventType.STATE_ROOM_BEACON_INFO.unstable val sendStateTaskParams = SendStateTask.Params( roomId = params.roomId, stateKey = userId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StopLiveLocationShareTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StopLiveLocationShareTask.kt index 40f7aa2dd2..e1e6fa9d40 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StopLiveLocationShareTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StopLiveLocationShareTask.kt @@ -45,7 +45,7 @@ internal class DefaultStopLiveLocationShareTask @Inject constructor( val sendStateTaskParams = SendStateTask.Params( roomId = params.roomId, stateKey = stateKey, - eventType = EventType.STATE_ROOM_BEACON_INFO.stable, + eventType = EventType.STATE_ROOM_BEACON_INFO.unstable, body = updatedContent ) return try { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt index 2f8be69473..8be6b26249 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt @@ -181,7 +181,7 @@ internal class LocalEchoEventFactory @Inject constructor( originServerTs = dummyOriginServerTs(), senderId = userId, eventId = localId, - type = EventType.POLL_START.stable, + type = EventType.POLL_START.unstable, content = newContent.toContent().plus(additionalContent.orEmpty()) ) } @@ -206,7 +206,7 @@ internal class LocalEchoEventFactory @Inject constructor( originServerTs = dummyOriginServerTs(), senderId = userId, eventId = localId, - type = EventType.POLL_RESPONSE.stable, + type = EventType.POLL_RESPONSE.unstable, content = content.toContent().plus(additionalContent.orEmpty()), unsignedData = UnsignedData(age = null, transactionId = localId) ) @@ -226,7 +226,7 @@ internal class LocalEchoEventFactory @Inject constructor( originServerTs = dummyOriginServerTs(), senderId = userId, eventId = localId, - type = EventType.POLL_START.stable, + type = EventType.POLL_START.unstable, content = content.toContent().plus(additionalContent.orEmpty()), unsignedData = UnsignedData(age = null, transactionId = localId) ) @@ -249,7 +249,7 @@ internal class LocalEchoEventFactory @Inject constructor( originServerTs = dummyOriginServerTs(), senderId = userId, eventId = localId, - type = EventType.POLL_END.stable, + type = EventType.POLL_END.unstable, content = content.toContent().plus(additionalContent.orEmpty()), unsignedData = UnsignedData(age = null, transactionId = localId) ) @@ -300,7 +300,7 @@ internal class LocalEchoEventFactory @Inject constructor( originServerTs = dummyOriginServerTs(), senderId = userId, eventId = localId, - type = EventType.BEACON_LOCATION_DATA.stable, + type = EventType.BEACON_LOCATION_DATA.unstable, content = content.toContent().plus(additionalContent.orEmpty()), unsignedData = UnsignedData(age = null, transactionId = localId) ) diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/aggregation/poll/PollEventsTestData.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/aggregation/poll/PollEventsTestData.kt index bdd1fd9b0d..e38b51132d 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/aggregation/poll/PollEventsTestData.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/aggregation/poll/PollEventsTestData.kt @@ -87,7 +87,7 @@ object PollEventsTestData { ) internal val A_POLL_START_EVENT = Event( - type = EventType.POLL_START.stable, + type = EventType.POLL_START.unstable, eventId = AN_EVENT_ID, originServerTs = 1652435922563, senderId = A_USER_ID_1, @@ -96,7 +96,7 @@ object PollEventsTestData { ) internal val A_POLL_RESPONSE_EVENT = Event( - type = EventType.POLL_RESPONSE.stable, + type = EventType.POLL_RESPONSE.unstable, eventId = AN_EVENT_ID, originServerTs = 1652435922563, senderId = A_USER_ID_1, @@ -105,7 +105,7 @@ object PollEventsTestData { ) internal val A_POLL_END_EVENT = Event( - type = EventType.POLL_END.stable, + type = EventType.POLL_END.unstable, eventId = AN_EVENT_ID, originServerTs = 1652435922563, senderId = A_USER_ID_1, diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultGetActiveBeaconInfoForUserTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultGetActiveBeaconInfoForUserTaskTest.kt index 4a10795647..6f416a6bc1 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultGetActiveBeaconInfoForUserTaskTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultGetActiveBeaconInfoForUserTaskTest.kt @@ -69,7 +69,7 @@ class DefaultGetActiveBeaconInfoForUserTaskTest { result shouldBeEqualTo currentStateEvent fakeStateEventDataSource.verifyGetStateEvent( roomId = params.roomId, - eventType = EventType.STATE_ROOM_BEACON_INFO.stable, + eventType = EventType.STATE_ROOM_BEACON_INFO.unstable, stateKey = QueryStringValue.Equals(A_USER_ID) ) } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStartLiveLocationShareTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStartLiveLocationShareTaskTest.kt index a5c126cf72..3156287774 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStartLiveLocationShareTaskTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStartLiveLocationShareTaskTest.kt @@ -75,7 +75,7 @@ internal class DefaultStartLiveLocationShareTaskTest { val expectedParams = SendStateTask.Params( roomId = params.roomId, stateKey = A_USER_ID, - eventType = EventType.STATE_ROOM_BEACON_INFO.stable, + eventType = EventType.STATE_ROOM_BEACON_INFO.unstable, body = expectedBeaconContent ) fakeSendStateTask.verifyExecuteRetry( diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStopLiveLocationShareTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStopLiveLocationShareTaskTest.kt index a7adadfc63..03c6f525e0 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStopLiveLocationShareTaskTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStopLiveLocationShareTaskTest.kt @@ -79,7 +79,7 @@ class DefaultStopLiveLocationShareTaskTest { val expectedSendParams = SendStateTask.Params( roomId = params.roomId, stateKey = A_USER_ID, - eventType = EventType.STATE_ROOM_BEACON_INFO.stable, + eventType = EventType.STATE_ROOM_BEACON_INFO.unstable, body = expectedBeaconContent ) fakeSendStateTask.verifyExecuteRetry( diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/LiveLocationShareRedactionEventProcessorTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/LiveLocationShareRedactionEventProcessorTest.kt index d6edb69d93..8dc7a5c9bc 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/LiveLocationShareRedactionEventProcessorTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/LiveLocationShareRedactionEventProcessorTest.kt @@ -79,7 +79,7 @@ class LiveLocationShareRedactionEventProcessorTest { @Test fun `given a redacted live location share event when processing it then related summaries are deleted from database`() = runTest { val event = Event(eventId = AN_EVENT_ID, redacts = A_REDACTED_EVENT_ID) - val redactedEventEntity = EventEntity(eventId = A_REDACTED_EVENT_ID, type = EventType.STATE_ROOM_BEACON_INFO.stable) + val redactedEventEntity = EventEntity(eventId = A_REDACTED_EVENT_ID, type = EventType.STATE_ROOM_BEACON_INFO.unstable) fakeRealm.givenWhere() .givenEqualTo(EventEntityFields.EVENT_ID, A_REDACTED_EVENT_ID) .givenFindFirst(redactedEventEntity) diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeCreatePollViewStates.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeCreatePollViewStates.kt index 42a500671b..3be1f5c643 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeCreatePollViewStates.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeCreatePollViewStates.kt @@ -63,7 +63,7 @@ object FakeCreatePollViewStates { ) private val A_POLL_START_EVENT = Event( - type = EventType.POLL_START.stable, + type = EventType.POLL_START.unstable, eventId = A_FAKE_EVENT_ID, originServerTs = 1652435922563, senderId = A_FAKE_USER_ID, From 99942c271451f1586c599c0232b078aa90026747 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Fri, 9 Dec 2022 09:33:06 +0100 Subject: [PATCH 16/20] Adding changelog entry --- changelog.d/7751.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7751.bugfix diff --git a/changelog.d/7751.bugfix b/changelog.d/7751.bugfix new file mode 100644 index 0000000000..5d676dbc4d --- /dev/null +++ b/changelog.d/7751.bugfix @@ -0,0 +1 @@ +Revert usage of stable fields in live location sharing and polls From cf59c80100d7a4b9ec02f62a43a6350e88fe2e0a Mon Sep 17 00:00:00 2001 From: Nikita Fedrunov <66663241+fedrunov@users.noreply.github.com> Date: Fri, 9 Dec 2022 09:42:45 +0100 Subject: [PATCH 17/20] stop listening timeline collection changes when app is not resumed (#7734) --- changelog.d/7643.bugfix | 1 + .../vector/app/features/home/room/detail/TimelineFragment.kt | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog.d/7643.bugfix diff --git a/changelog.d/7643.bugfix b/changelog.d/7643.bugfix new file mode 100644 index 0000000000..66e3f28d5f --- /dev/null +++ b/changelog.d/7643.bugfix @@ -0,0 +1 @@ +[Notifications] Fixed a bug when push notification was automatically dismissed while app is on background diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index b73d443832..6ab20275c2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -975,6 +975,7 @@ class TimelineFragment : notificationDrawerManager.setCurrentThread(timelineArgs.threadTimelineArgs?.rootThreadEventId) roomDetailPendingActionStore.data?.let { handlePendingAction(it) } roomDetailPendingActionStore.data = null + views.timelineRecyclerView.adapter = timelineEventController.adapter } private fun handlePendingAction(roomDetailPendingAction: RoomDetailPendingAction) { @@ -993,6 +994,7 @@ class TimelineFragment : super.onPause() notificationDrawerManager.setCurrentRoom(null) notificationDrawerManager.setCurrentThread(null) + views.timelineRecyclerView.adapter = null } private val emojiActivityResultLauncher = registerStartForActivityResult { activityResult -> @@ -1058,7 +1060,6 @@ class TimelineFragment : it.dispatchTo(scrollOnHighlightedEventCallback) } timelineEventController.addModelBuildListener(modelBuildListener) - views.timelineRecyclerView.adapter = timelineEventController.adapter if (vectorPreferences.swipeToReplyIsEnabled()) { val quickReplyHandler = object : RoomMessageTouchHelperCallback.QuickReplayHandler { From 74d7e60380caf3a625cd47cf67ef150e1664c821 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 09:21:24 +0100 Subject: [PATCH 18/20] Bump fragment from 1.5.4 to 1.5.5 (#7741) Bumps `fragment` from 1.5.4 to 1.5.5. Updates `fragment-ktx` from 1.5.4 to 1.5.5 Updates `fragment-testing` from 1.5.4 to 1.5.5 --- updated-dependencies: - dependency-name: androidx.fragment:fragment-ktx dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: androidx.fragment:fragment-testing dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index a9aee3b681..dbb5f5fe05 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -27,7 +27,7 @@ def jjwt = "0.11.5" // the whole commit which set version 0.16.0-SNAPSHOT def vanniktechEmoji = "0.16.0-SNAPSHOT" def sentry = "6.9.0" -def fragment = "1.5.4" +def fragment = "1.5.5" // Testing def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819 def espresso = "3.4.0" From a12167077f378bf0aecbe4e1e4b793457b2902b9 Mon Sep 17 00:00:00 2001 From: Ekaterina Gerasimova Date: Fri, 9 Dec 2022 12:19:43 +0000 Subject: [PATCH 19/20] Update project board IDs for automation "PN-" prefixed IDs are no longer working, update to new IDs --- .github/workflows/triage-labelled.yml | 16 ++++++++-------- .../workflows/triage-move-review-requests.yml | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml index 41cd274b93..036bc069ac 100644 --- a/.github/workflows/triage-labelled.yml +++ b/.github/workflows/triage-labelled.yml @@ -89,7 +89,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc0sUA" + PROJECT_ID: "PVT_kwDOAM0swc0sUA" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} add_product_issues: @@ -113,7 +113,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc4AAg6N" + PROJECT_ID: "PVT_kwDOAM0swc4AAg6N" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} delight_issues_to_board: @@ -139,7 +139,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc1HvQ" + PROJECT_ID: "PVT_kwDOAM0swc1HvQ" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} move_voice-message_issues: @@ -164,7 +164,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc2KCw" + PROJECT_ID: "PVT_kwDOAM0swc2KCw" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} move_message_bubbles_issues: name: A-Message-Bubbles to Message bubbles board @@ -188,7 +188,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc3m-g" + PROJECT_ID: "PVT_kwDOAM0swc3m-g" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} move_ftue_issues: @@ -213,7 +213,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc4AAqVx" + PROJECT_ID: "PVT_kwDOAM0swc4AAqVx" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} move_WTF_issues: @@ -238,7 +238,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc4AArk0" + PROJECT_ID: "PVT_kwDOAM0swc4AArk0" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} move_element_x_issues: @@ -268,7 +268,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc4ABTXY" + PROJECT_ID: "PVT_kwDOAM0swc4ABTXY" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} ps_features1: diff --git a/.github/workflows/triage-move-review-requests.yml b/.github/workflows/triage-move-review-requests.yml index 6aeba66ccc..f604b82873 100644 --- a/.github/workflows/triage-move-review-requests.yml +++ b/.github/workflows/triage-move-review-requests.yml @@ -69,7 +69,7 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.pull_request.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc0sUA" + PROJECT_ID: "PVT_kwDOAM0swc0sUA" TEAM: "design" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -138,6 +138,6 @@ jobs: projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.pull_request.node_id }} env: - PROJECT_ID: "PN_kwDOAM0swc4AAg6N" + PROJECT_ID: "PVT_kwDOAM0swc4AAg6N" TEAM: "product" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} From c523e144b816d313e356c2ab1a1a7db4ff99ba30 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 12 Dec 2022 13:52:17 +0100 Subject: [PATCH 20/20] Rich text editor: improve performance when changing composer mode (#7691) * Rich text editor: improve performance when changing composer mode * Add changelog * Make `MessageComposerMode.Quote` and `Reply` data classes * Re-arrange code to fix composer not being emptied when sneding a message --- changelog.d/7691.bugfix | 1 + .../composer/MessageComposerFragment.kt | 2 +- .../detail/composer/MessageComposerMode.kt | 4 +-- .../detail/composer/RichTextComposerLayout.kt | 25 ++++++++++++++----- 4 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 changelog.d/7691.bugfix diff --git a/changelog.d/7691.bugfix b/changelog.d/7691.bugfix new file mode 100644 index 0000000000..0298819143 --- /dev/null +++ b/changelog.d/7691.bugfix @@ -0,0 +1 @@ +Rich Text Editor: improve performance when entering reply/edit/quote mode. diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt index bf9e0ae726..d56ea8b733 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt @@ -285,7 +285,7 @@ class MessageComposerFragment : VectorBaseFragment(), A else -> return } - (composer as? RichTextComposerLayout)?.setFullScreen(setFullScreen) + (composer as? RichTextComposerLayout)?.setFullScreen(setFullScreen, true) messageComposerViewModel.handle(MessageComposerAction.SetFullScreen(setFullScreen)) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerMode.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerMode.kt index a401f04bf5..89cb148639 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerMode.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerMode.kt @@ -23,6 +23,6 @@ sealed interface MessageComposerMode { sealed class Special(open val event: TimelineEvent, open val defaultContent: CharSequence) : MessageComposerMode data class Edit(override val event: TimelineEvent, override val defaultContent: CharSequence) : Special(event, defaultContent) - class Quote(override val event: TimelineEvent, override val defaultContent: CharSequence) : Special(event, defaultContent) - class Reply(override val event: TimelineEvent, override val defaultContent: CharSequence) : Special(event, defaultContent) + data class Quote(override val event: TimelineEvent, override val defaultContent: CharSequence) : Special(event, defaultContent) + data class Reply(override val event: TimelineEvent, override val defaultContent: CharSequence) : Special(event, defaultContent) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt index 16234c3766..d69fe8edeb 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt @@ -66,6 +66,7 @@ internal class RichTextComposerLayout @JvmOverloads constructor( // There is no need to persist these values since they're always updated by the parent fragment private var isFullScreen = false private var hasRelatedMessage = false + private var composerMode: MessageComposerMode? = null var isTextFormattingEnabled = true set(value) { @@ -114,9 +115,15 @@ internal class RichTextComposerLayout @JvmOverloads constructor( private val dimensionConverter = DimensionConverter(resources) - fun setFullScreen(isFullScreen: Boolean) { + fun setFullScreen(isFullScreen: Boolean, animated: Boolean) { + if (!animated && views.composerLayout.layoutParams != null) { + views.composerLayout.updateLayoutParams { + height = + if (isFullScreen) ViewGroup.LayoutParams.MATCH_PARENT else ViewGroup.LayoutParams.WRAP_CONTENT + } + } editText.updateLayoutParams { - height = if (isFullScreen) 0 else ViewGroup.LayoutParams.WRAP_CONTENT + height = if (isFullScreen) ViewGroup.LayoutParams.MATCH_PARENT else ViewGroup.LayoutParams.WRAP_CONTENT } updateTextFieldBorder(isFullScreen) @@ -371,7 +378,11 @@ internal class RichTextComposerLayout @JvmOverloads constructor( override fun renderComposerMode(mode: MessageComposerMode) { if (mode is MessageComposerMode.Special) { views.composerModeGroup.isVisible = true - replaceFormattedContent(mode.defaultContent) + if (isTextFormattingEnabled) { + replaceFormattedContent(mode.defaultContent) + } else { + views.plainTextComposerEditText.setText(mode.defaultContent) + } hasRelatedMessage = true editText.showKeyboard(andRequestFocus = true) } else { @@ -383,10 +394,14 @@ internal class RichTextComposerLayout @JvmOverloads constructor( views.plainTextComposerEditText.setText(text) } } - views.sendButton.contentDescription = resources.getString(R.string.action_send) hasRelatedMessage = false } + updateTextFieldBorder(isFullScreen) + + if (this.composerMode == mode) return + this.composerMode = mode + views.sendButton.apply { if (mode is MessageComposerMode.Edit) { contentDescription = resources.getString(R.string.action_save) @@ -397,8 +412,6 @@ internal class RichTextComposerLayout @JvmOverloads constructor( } } - updateTextFieldBorder(isFullScreen) - when (mode) { is MessageComposerMode.Edit -> { views.composerModeTitleView.setText(R.string.editing)