diff --git a/CHANGES.md b/CHANGES.md index e5ce4dc1ab..6d756f2b3f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,20 @@ +Changes in Element v1.6.1 (2023-05-25) +====================================== + +Corrective release for 1.6.0 + +Bugfixes 🐛 +---------- + - Allow stateloss on verification dialogfragment ([#8439](https://github.com/vector-im/element-android/issues/8439)) + - Fix: Update verification popup text when a re-verification is needed after rust migration (read only sessions) ([#8445](https://github.com/vector-im/element-android/issues/8445)) + - Fix several performance issues causing app non responsive issues. ([#8454](https://github.com/vector-im/element-android/issues/8454)) + - Fix: The device list screen from the member profile page was always showing the current user devices (rust crypto). ([#8457](https://github.com/vector-im/element-android/issues/8457)) + +Other changes +------------- + - Remove UI option to manually verify a specific device of another user (deprecated behaviour) ([#8458](https://github.com/vector-im/element-android/issues/8458)) + + Changes in Element v1.6.0 (2023-05-17) ====================================== diff --git a/build.gradle b/build.gradle index 3060747977..a70b54a833 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ buildscript { classpath 'com.google.gms:google-services:4.3.15' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:4.0.0.2929' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6' - classpath "com.likethesalad.android:stem-plugin:2.4.0" + classpath "com.likethesalad.android:stem-plugin:2.4.1" classpath 'org.owasp:dependency-check-gradle:8.2.1' classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.8.10" classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0" diff --git a/dependencies.gradle b/dependencies.gradle index 5f4df15860..ca5495b04d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -101,7 +101,7 @@ ext.libs = [ ], element : [ 'opusencoder' : "io.element.android:opusencoder:1.1.0", - 'wysiwyg' : "io.element.android:wysiwyg:1.2.2" + 'wysiwyg' : "io.element.android:wysiwyg:2.2.1" ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", diff --git a/fastlane/metadata/android/en-US/changelogs/40106010.txt b/fastlane/metadata/android/en-US/changelogs/40106010.txt new file mode 100644 index 0000000000..badf979955 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Main changes in this version: Element Android is now using the Crypto Rust SDK. +Full changelog: https://github.com/vector-im/element-android/releases diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index 3d1a36d4c3..8ad9ad6eb4 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -2446,6 +2446,7 @@ Verify this device + App updated Unable to verify this device You won’t be able to access encrypted message history. Reset your Secure Message Backup and verification keys to start fresh. @@ -2465,7 +2466,9 @@ This session is trusted for secure messaging because %1$s (%2$s) verified it: %1$s (%2$s) signed in using a new session: - Until this user trusts this session, messages sent to and from it are labeled with warnings. Alternatively, you can manually verify it. + + Until this user trusts this session, messages sent to and from it are labeled with warnings. Alternatively, you can manually verify it. + Until this user trusts this session, messages sent to and from it are labeled with warnings. Initialize CrossSigning @@ -2707,6 +2710,7 @@ Verify login Interactively Verify by Emoji Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages. + Secure messaging has been improved with the latest update. Please re-verify your device. Confirm your identity by verifying this login, granting it access to encrypted messages. Failed to set up Cross Signing diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 3c1f970bee..230677e8e2 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -63,7 +63,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.6.0\"" + buildConfigField "String", "SDK_VERSION", "\"1.6.1\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt index 8e7592a8b4..5c44931009 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/SetReadMarkersTask.kt @@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.session.room.read import com.zhuinden.monarchy.Monarchy import io.realm.Realm +import kotlinx.coroutines.withContext +import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.session.events.model.LocalEcho import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity @@ -64,9 +66,10 @@ internal class DefaultSetReadMarkersTask @Inject constructor( private val globalErrorReceiver: GlobalErrorReceiver, private val clock: Clock, private val homeServerCapabilitiesService: HomeServerCapabilitiesService, + private val coroutineDispatchers: MatrixCoroutineDispatchers, ) : SetReadMarkersTask { - override suspend fun execute(params: SetReadMarkersTask.Params) { + override suspend fun execute(params: SetReadMarkersTask.Params) = withContext(coroutineDispatchers.io) { val markers = mutableMapOf() Timber.v("Execute set read marker with params: $params") val latestSyncedEventId = latestSyncedEventId(params.roomId) diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt index 4769d57dc9..6d96c2c836 100755 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt @@ -360,9 +360,7 @@ internal class RustCryptoService @Inject constructor( } override fun getLiveCryptoDeviceInfo(userIds: List): LiveData> { - return olmMachine.getLiveDevices(listOf(myUserId)).map { - it.filter { it.userId == myUserId } - } + return olmMachine.getLiveDevices(userIds) } override fun getLiveCryptoDeviceInfoWithId(deviceId: String): LiveData> { diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/migration/rust/ExtractUtils.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/migration/rust/ExtractUtils.kt index 608f68fc3d..d99403fe19 100644 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/migration/rust/ExtractUtils.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/store/db/migration/rust/ExtractUtils.kt @@ -71,6 +71,10 @@ fun RealmToMigrate.getPickledAccount(pickleKey: ByteArray): MigrationData { val userKey = metadataEntity.xSignUserPrivateKey val selfSignedKey = metadataEntity.xSignSelfSignedPrivateKey + Timber.i("## Migration: has private MSK ${masterKey.isNullOrBlank().not()}") + Timber.i("## Migration: has private USK ${userKey.isNullOrBlank().not()}") + Timber.i("## Migration: has private SSK ${selfSignedKey.isNullOrBlank().not()}") + val userId = metadataEntity.userId ?: throw java.lang.IllegalArgumentException("Rust db migration: userId is null") val deviceId = metadataEntity.deviceId @@ -79,6 +83,8 @@ fun RealmToMigrate.getPickledAccount(pickleKey: ByteArray): MigrationData { val backupVersion = metadataEntity.backupVersion val backupRecoveryKey = metadataEntity.keyBackupRecoveryKey + Timber.i("## Migration: has private backup key ${backupRecoveryKey != null} for version $backupVersion") + val isOlmAccountShared = metadataEntity.deviceKeysSentToServer val olmAccount = metadataEntity.getOlmAccount() diff --git a/tools/release/releaseScript.sh b/tools/release/releaseScript.sh index e140560e52..f198670eae 100755 --- a/tools/release/releaseScript.sh +++ b/tools/release/releaseScript.sh @@ -267,7 +267,7 @@ fi printf "\n================================================================================\n" printf "Wait for the GitHub action https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%%3Amain to build the 'main' branch.\n" -read -p "After GHA is finished, please enter the artifact URL (for 'vector-gplay-rustCrypto-release-unsigned'): " artifactUrl +read -p "After GHA is finished, please enter the artifact URL (for 'vector-gplay-release-unsigned'): " artifactUrl printf "\n================================================================================\n" printf "Downloading the artifact...\n" @@ -290,7 +290,7 @@ set -e printf "\n================================================================================\n" printf "Unzipping the artifact...\n" -unzip ${targetPath}/vector-gplay-rustCrypto-release-unsigned.zip -d ${targetPath} +unzip ${targetPath}/vector-gplay-release-unsigned.zip -d ${targetPath} # Flatten folder hierarchy mv ${targetPath}/gplayRustCrypto/release/* ${targetPath} diff --git a/vector-app/build.gradle b/vector-app/build.gradle index ebcc9c76ac..28ccc03815 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -37,7 +37,7 @@ ext.versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -ext.versionPatch = 0 +ext.versionPatch = 1 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' diff --git a/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt b/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt index ebbe565642..fe6f6cb987 100644 --- a/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt +++ b/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt @@ -23,7 +23,7 @@ import android.text.Spanned import android.text.style.StrikethroughSpan import androidx.core.text.getSpans import im.vector.app.features.html.HtmlCodeSpan -import io.element.android.wysiwyg.spans.InlineCodeSpan +import io.element.android.wysiwyg.view.spans.InlineCodeSpan import io.mockk.justRun import io.mockk.mockk import io.mockk.slot diff --git a/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteUnusedClientInformationUseCase.kt b/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteUnusedClientInformationUseCase.kt index dcd5c58480..cc5dc6725d 100644 --- a/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteUnusedClientInformationUseCase.kt +++ b/vector/src/main/java/im/vector/app/core/session/clientinfo/DeleteUnusedClientInformationUseCase.kt @@ -17,6 +17,7 @@ package im.vector.app.core.session.clientinfo import im.vector.app.core.di.ActiveSessionHolder +import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import javax.inject.Inject @@ -27,16 +28,19 @@ class DeleteUnusedClientInformationUseCase @Inject constructor( suspend fun execute(deviceInfoList: List): Result = runCatching { // A defensive approach against local storage reports an empty device list (although it is not a seen situation). if (deviceInfoList.isEmpty()) return Result.success(Unit) - - val expectedClientInfoKeyList = deviceInfoList.map { MATRIX_CLIENT_INFO_KEY_PREFIX + it.deviceId } - activeSessionHolder - .getSafeActiveSession() - ?.accountDataService() - ?.getUserAccountDataEventsStartWith(MATRIX_CLIENT_INFO_KEY_PREFIX) - ?.map { it.type } - ?.subtract(expectedClientInfoKeyList.toSet()) - ?.forEach { userAccountDataKeyToDelete -> - activeSessionHolder.getSafeActiveSession()?.accountDataService()?.deleteUserAccountData(userAccountDataKeyToDelete) - } + val dispatcher = activeSessionHolder.getSafeActiveSession()?.coroutineDispatchers?.io + ?: return@runCatching + withContext(dispatcher) { + val expectedClientInfoKeyList = deviceInfoList.map { MATRIX_CLIENT_INFO_KEY_PREFIX + it.deviceId } + activeSessionHolder + .getSafeActiveSession() + ?.accountDataService() + ?.getUserAccountDataEventsStartWith(MATRIX_CLIENT_INFO_KEY_PREFIX) + ?.map { it.type } + ?.subtract(expectedClientInfoKeyList.toSet()) + ?.forEach { userAccountDataKeyToDelete -> + activeSessionHolder.getSafeActiveSession()?.accountDataService()?.deleteUserAccountData(userAccountDataKeyToDelete) + } + } } } diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt index cffb1577cf..ff0e9721e4 100644 --- a/vector/src/main/java/im/vector/app/features/MainActivity.kt +++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt @@ -29,6 +29,7 @@ import com.airbnb.mvrx.viewModel import com.bumptech.glide.Glide import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.BuildConfig import im.vector.app.R import im.vector.app.core.extensions.startSyncing import im.vector.app.core.extensions.vectorStore @@ -170,6 +171,19 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity } private fun handleAppStarted() { + // On the first run with rust crypto this would be false + if (!vectorPreferences.isOnRustCrypto()) { + if (activeSessionHolder.hasActiveSession()) { + vectorPreferences.setHadExistingLegacyData(activeSessionHolder.getActiveSession().isOpenable) + } else { + vectorPreferences.setHadExistingLegacyData(false) + } + } + + if (BuildConfig.FLAVOR == "rustCrypto") { + vectorPreferences.setIsOnRustCrypto(true) + } + if (intent.hasExtra(EXTRA_NEXT_INTENT)) { // Start the next Activity startSyncing() diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt index 66344107a4..d060e3996d 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageResetAllFragment.kt @@ -52,7 +52,7 @@ class SharedSecuredStorageResetAllFragment : views.ssssResetOtherDevices.debouncedClicks { withState(sharedViewModel) { - DeviceListBottomSheet.newInstance(it.userId, false).show(childFragmentManager, "DEV_LIST") + DeviceListBottomSheet.newInstance(it.userId).show(childFragmentManager, "DEV_LIST") } } 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 42eb200887..428e62724b 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 @@ -469,11 +469,21 @@ class HomeActivity : private fun handleOnNewSession(event: HomeActivityViewEvents.CurrentSessionNotVerified) { // We need to ask + val titleRes = if (event.afterMigration) { + R.string.crosssigning_verify_after_update + } else { + R.string.crosssigning_verify_this_session + } + val descRes = if (event.afterMigration) { + R.string.confirm_your_identity_after_update + } else { + R.string.confirm_your_identity + } promptSecurityEvent( uid = PopupAlertManager.VERIFY_SESSION_UID, userItem = event.userItem, - titleRes = R.string.crosssigning_verify_this_session, - descRes = R.string.confirm_your_identity, + titleRes = titleRes, + descRes = descRes, ) { it.navigator.requestSelfSessionVerification(it) } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt index 5f8d9cdc51..c57f32694b 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt @@ -23,7 +23,7 @@ sealed interface HomeActivityViewEvents : VectorViewEvents { data class AskPasswordToInitCrossSigning(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents data class CurrentSessionNotVerified( val userItem: MatrixItem.UserItem, -// val waitForIncomingRequest: Boolean = true, + val afterMigration: Boolean ) : HomeActivityViewEvents data class CurrentSessionCannotBeVerified( diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index 73bbcac070..eb4a796a49 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -453,6 +453,7 @@ class HomeActivityViewModel @AssistedInject constructor( _viewEvents.post( HomeActivityViewEvents.CurrentSessionNotVerified( session.getUserOrDefault(session.myUserId).toMatrixItem(), + vectorPreferences.isOnRustCrypto() && vectorPreferences.hadExistingLegacyData() ) ) } else { 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 a821458939..49e8f0cdc6 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 @@ -50,9 +50,9 @@ import im.vector.app.databinding.ComposerRichTextLayoutBinding import im.vector.app.databinding.ViewRichTextMenuButtonBinding import im.vector.app.features.home.room.detail.composer.images.UriContentListener import io.element.android.wysiwyg.EditorEditText -import io.element.android.wysiwyg.inputhandlers.models.InlineFormat -import io.element.android.wysiwyg.inputhandlers.models.LinkAction import io.element.android.wysiwyg.utils.RustErrorCollector +import io.element.android.wysiwyg.view.models.InlineFormat +import io.element.android.wysiwyg.view.models.LinkAction import uniffi.wysiwyg_composer.ActionState import uniffi.wysiwyg_composer.ComposerAction @@ -269,7 +269,7 @@ internal class RichTextComposerLayout @JvmOverloads constructor( views.richTextComposerEditText.getLinkAction()?.let { when (it) { LinkAction.InsertLink -> callback?.onSetLink(isTextSupported = true, initialLink = null) - is LinkAction.SetLink -> callback?.onSetLink(isTextSupported = false, initialLink = it.currentLink) + is LinkAction.SetLink -> callback?.onSetLink(isTextSupported = false, initialLink = it.currentUrl) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt index 74b55d435d..fad1ad613d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt @@ -322,11 +322,10 @@ class RoomListViewModel @AssistedInject constructor( } private fun handleDeleteLocalRooms() { - val localRoomIds = session.roomService() - .getRoomSummaries(roomSummaryQueryParams { roomId = QueryStringValue.Contains(RoomLocalEcho.PREFIX) }) - .map { it.roomId } - - viewModelScope.launch { + viewModelScope.launch(session.coroutineDispatchers.io) { + val localRoomIds = session.roomService() + .getRoomSummaries(roomSummaryQueryParams { roomId = QueryStringValue.Contains(RoomLocalEcho.PREFIX) }) + .map { it.roomId } localRoomIds.forEach { session.roomService().deleteLocalRoom(it) } diff --git a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt index cb3f12d867..5874474965 100644 --- a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt @@ -43,7 +43,7 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.ColorProvider import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences -import io.element.android.wysiwyg.spans.InlineCodeSpan +import io.element.android.wysiwyg.view.spans.InlineCodeSpan import io.noties.markwon.AbstractMarkwonPlugin import io.noties.markwon.Markwon import io.noties.markwon.MarkwonPlugin diff --git a/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt b/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt index 3175996ba1..7ffd9ceb84 100644 --- a/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt +++ b/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt @@ -18,8 +18,8 @@ package im.vector.app.features.html import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences -import io.element.android.wysiwyg.spans.CodeBlockSpan -import io.element.android.wysiwyg.spans.InlineCodeSpan +import io.element.android.wysiwyg.view.spans.CodeBlockSpan +import io.element.android.wysiwyg.view.spans.InlineCodeSpan import io.noties.markwon.MarkwonVisitor import io.noties.markwon.SpannableBuilder import io.noties.markwon.core.MarkwonTheme diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index d2628fcf0f..b38805f05a 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -38,6 +38,7 @@ import im.vector.app.config.OnboardingVariant import im.vector.app.core.debug.DebugNavigator import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.error.fatalError +import im.vector.app.core.extensions.commitTransaction import im.vector.app.features.VectorFeatures import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.extensions.toAnalyticsViewRoom @@ -256,8 +257,9 @@ class DefaultNavigator @Inject constructor( otherSessionId ) if (context is AppCompatActivity) { - SelfVerificationBottomSheet.forTransaction(request.transactionId) - .show(context.supportFragmentManager, "VERIF") + context.supportFragmentManager.commitTransaction(allowStateLoss = true) { + add(SelfVerificationBottomSheet.forTransaction(request.transactionId), "VERIF") + } } } } @@ -271,8 +273,9 @@ class DefaultNavigator @Inject constructor( // .filter { it.deviceId != session.sessionParams.deviceId } // .map { it.deviceId } if (context is AppCompatActivity) { - SelfVerificationBottomSheet.verifyOwnUntrustedDevice() - .show(context.supportFragmentManager, "VERIF") + context.supportFragmentManager.commitTransaction(allowStateLoss = true) { + add(SelfVerificationBottomSheet.verifyOwnUntrustedDevice(), "VERIF") + } // if (otherSessions.isNotEmpty()) { // val pr = session.cryptoService().verificationService().requestSelfKeyVerification( // supportedVerificationMethodsProvider.provide()) diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt index 2d799034d9..61cb14a70f 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt @@ -24,7 +24,9 @@ import im.vector.app.R import im.vector.app.core.resources.BuildMeta import im.vector.app.core.utils.FirstThrottler import im.vector.app.features.displayname.getBestName +import im.vector.app.features.session.coroutineScope import im.vector.app.features.settings.VectorPreferences +import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.content.ContentUrlResolver import org.matrix.android.sdk.api.session.getUserOrDefault @@ -121,11 +123,15 @@ class NotificationDrawerManager @Inject constructor( * Used to ignore events related to that room (no need to display notification) and clean any existing notification on this room. */ fun setCurrentRoom(roomId: String?) { - updateEvents { - val hasChanged = roomId != currentRoomId - currentRoomId = roomId - if (hasChanged && roomId != null) { - it.clearMessagesForRoom(roomId) + val dispatcher = currentSession?.coroutineDispatchers?.io ?: return + val scope = currentSession?.coroutineScope ?: return + scope.launch(dispatcher) { + updateEvents { + val hasChanged = roomId != currentRoomId + currentRoomId = roomId + if (hasChanged && roomId != null) { + it.clearMessagesForRoom(roomId) + } } } } @@ -135,12 +141,16 @@ class NotificationDrawerManager @Inject constructor( * Used to ignore events related to that thread (no need to display notification) and clean any existing notification on this room. */ fun setCurrentThread(threadId: String?) { - updateEvents { - val hasChanged = threadId != currentThreadId - currentThreadId = threadId - currentRoomId?.let { roomId -> - if (hasChanged && threadId != null) { - it.clearMessagesForThread(roomId, threadId) + val dispatcher = currentSession?.coroutineDispatchers?.io ?: return + val scope = currentSession?.coroutineScope ?: return + scope.launch(dispatcher) { + updateEvents { + val hasChanged = threadId != currentThreadId + currentThreadId = threadId + currentRoomId?.let { roomId -> + if (hasChanged && threadId != null) { + it.clearMessagesForThread(roomId, threadId) + } } } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt index c269a4166a..09ae73a55c 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt @@ -22,6 +22,4 @@ import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo sealed class DeviceListAction : VectorViewModelAction { data class SelectDevice(val device: CryptoDeviceInfo) : DeviceListAction() object DeselectDevice : DeviceListAction() - - data class ManuallyVerify(val deviceId: String) : DeviceListAction() } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt index 2a0ca4850e..63c44b4000 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt @@ -47,16 +47,7 @@ class DeviceListBottomSheet : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.observeViewEvents { - when (it) { - is DeviceListBottomSheetViewEvents.Verify -> { - // TODO selfverif -// VerificationBottomSheet.withArgs( -// // roomId = null, -// otherUserId = it.userId, -// transactionId = it.txID -// ).show(requireActivity().supportFragmentManager, "REQPOP") - } - } + // nop } } @@ -109,13 +100,12 @@ class DeviceListBottomSheet : @Parcelize data class Args( val userId: String, - val allowDeviceAction: Boolean ) : Parcelable companion object { - fun newInstance(userId: String, allowDeviceAction: Boolean = true): DeviceListBottomSheet { + fun newInstance(userId: String): DeviceListBottomSheet { return DeviceListBottomSheet().apply { - setArguments(Args(userId, allowDeviceAction)) + setArguments(Args(userId)) } } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewEvents.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewEvents.kt index 8c6cba6cd9..159f505e16 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewEvents.kt @@ -21,6 +21,4 @@ import im.vector.app.core.platform.VectorViewEvents /** * Transient events for device list screen. */ -sealed class DeviceListBottomSheetViewEvents : VectorViewEvents { - data class Verify(val userId: String, val txID: String) : DeviceListBottomSheetViewEvents() -} +sealed class DeviceListBottomSheetViewEvents : VectorViewEvents diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt index c3281858f0..435c44aa11 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt @@ -34,7 +34,6 @@ import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.getUserOrDefault import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.toMatrixItem @@ -42,7 +41,7 @@ import org.matrix.android.sdk.flow.flow data class DeviceListViewState( val userId: String, - val allowDeviceAction: Boolean, + val myUserId: String, val userItem: MatrixItem? = null, val memberCrossSigningKey: MXCrossSigningInfo? = null, val myDeviceId: String = "", @@ -69,7 +68,7 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor( val session = EntryPoints.get(viewModelContext.app(), SingletonEntryPoint::class.java).activeSessionHolder().getActiveSession() return DeviceListViewState( userId = userId, - allowDeviceAction = args.allowDeviceAction, + myUserId = session.myUserId, userItem = session.getUserOrDefault(userId).toMatrixItem(), myDeviceId = session.sessionParams.deviceId, ) @@ -104,7 +103,6 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor( when (action) { is DeviceListAction.SelectDevice -> selectDevice(action) is DeviceListAction.DeselectDevice -> deselectDevice() - is DeviceListAction.ManuallyVerify -> manuallyVerify(action) } } @@ -121,7 +119,6 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor( } private fun selectDevice(action: DeviceListAction.SelectDevice) { - if (!initialState.allowDeviceAction) return setState { copy(selectedDevice = action.device) } @@ -132,18 +129,4 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor( copy(selectedDevice = null) } } - - private fun manuallyVerify(action: DeviceListAction.ManuallyVerify) { - if (!initialState.allowDeviceAction) return - viewModelScope.launch { - session.cryptoService().verificationService().requestDeviceVerification( - methods = listOf(VerificationMethod.SAS), - otherUserId = initialState.userId, - otherDeviceId = action.deviceId, - ).transactionId - .let { txID -> - _viewEvents.post(DeviceListBottomSheetViewEvents.Verify(initialState.userId, txID)) - } - } - } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt index d8abd91091..d3b5a25913 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt @@ -28,7 +28,6 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.DimensionConverter import im.vector.app.databinding.BottomSheetGenericListBinding -import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import javax.inject.Inject @AndroidEntryPoint @@ -63,8 +62,4 @@ class DeviceTrustInfoActionFragment : override fun invalidate() = withState(viewModel) { epoxyController.setData(it) } - - override fun onVerifyManually(device: CryptoDeviceInfo) { - viewModel.handle(DeviceListAction.ManuallyVerify(device.deviceId)) - } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt index 20c388dd95..0f39fc889c 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt @@ -25,13 +25,10 @@ import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericItem import im.vector.app.core.ui.list.genericWithValueItem import im.vector.app.core.utils.DimensionConverter -import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem -import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.devices.TrustUtils import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import javax.inject.Inject @@ -39,13 +36,10 @@ class DeviceTrustInfoEpoxyController @Inject constructor( private val stringProvider: StringProvider, private val colorProvider: ColorProvider, private val dimensionConverter: DimensionConverter, - private val vectorPreferences: VectorPreferences ) : TypedEpoxyController() { - interface InteractionListener { - fun onVerifyManually(device: CryptoDeviceInfo) - } + interface InteractionListener var interactionListener: InteractionListener? = null @@ -54,7 +48,7 @@ class DeviceTrustInfoEpoxyController @Inject constructor( data?.selectedDevice?.let { cryptoDeviceInfo -> val trustMSK = data.memberCrossSigningKey?.isTrusted().orFalse() val legacyMode = data.memberCrossSigningKey == null - val isMyDevice = data.myDeviceId == cryptoDeviceInfo.deviceId + val isMyDevice = data.userId == data.myUserId && data.myDeviceId == cryptoDeviceInfo.deviceId val trustLevel = TrustUtils.shieldForTrust( isMyDevice, trustMSK, @@ -126,18 +120,7 @@ class DeviceTrustInfoEpoxyController @Inject constructor( id("warn") centered(false) textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) - text(host.stringProvider.getString(R.string.verification_profile_device_untrust_info).toEpoxyCharSequence()) - } - - bottomSheetVerificationActionItem { - id("verify") - title(host.stringProvider.getString(R.string.cross_signing_verify_by_emoji)) - titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - iconRes(R.drawable.ic_arrow_right) - iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary)) - listener { - host.interactionListener?.onVerifyManually(cryptoDeviceInfo) - } + text(host.stringProvider.getString(R.string.verification_profile_other_device_untrust_info).toEpoxyCharSequence()) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index f915395a42..0dd8d14460 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -254,6 +254,8 @@ class VectorPreferences @Inject constructor( const val TAKE_PHOTO_VIDEO_MODE_PHOTO = 1 const val TAKE_PHOTO_VIDEO_MODE_VIDEO = 2 + const val HAD_EXISTING_LEGACY_DATA = "HAD_EXISTING_LEGACY_DATA" + const val IS_ON_RUST_CRYPTO = "IS_ON_RUST_CRYPTO" // Background sync modes // some preferences keys must be kept after a logout @@ -1278,4 +1280,24 @@ class VectorPreferences @Inject constructor( putBoolean(SETTINGS_NEW_LOGIN_ALERT_SHOWN_FOR_DEVICE + deviceId, true) } } + + fun hadExistingLegacyData(): Boolean { + return defaultPrefs.getBoolean(HAD_EXISTING_LEGACY_DATA, false) + } + + fun setHadExistingLegacyData(had: Boolean) { + defaultPrefs.edit { + putBoolean(HAD_EXISTING_LEGACY_DATA, had) + } + } + + fun isOnRustCrypto(): Boolean { + return defaultPrefs.getBoolean(IS_ON_RUST_CRYPTO, false) + } + + fun setIsOnRustCrypto(boolean: Boolean) { + defaultPrefs.edit { + putBoolean(IS_ON_RUST_CRYPTO, boolean) + } + } } 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 268ae86601..762a636494 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,6 +25,8 @@ class GetEncryptionTrustLevelForDeviceUseCase @Inject constructor( private val getEncryptionTrustLevelForOtherDeviceUseCase: GetEncryptionTrustLevelForOtherDeviceUseCase, ) { + // XXX why is this using the RoomEncryptionTrustLevel? + // should be using a new DeviceTrustShield enum fun execute(currentSessionCrossSigningInfo: CurrentSessionCrossSigningInfo, cryptoDeviceInfo: CryptoDeviceInfo?): RoomEncryptionTrustLevel? { if (cryptoDeviceInfo == null) { return null