diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index 7779bd1a0e..7f3675cb39 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -42,7 +42,7 @@ class RxRoom(private val room: Room, private val session: Session) { val summaryObservable = room.getRoomSummaryLive() .asObservable() .startWith(room.roomSummary().toOptional()) - .doOnNext { Timber.d("RX: summary emitted for: ${it.getOrNull()?.roomId}") } + .doOnNext { Timber.v("RX: summary emitted for: ${it.getOrNull()?.roomId}") } val memberIdsChangeObservable = summaryObservable .map { @@ -56,7 +56,7 @@ class RxRoom(private val room: Room, private val session: Session) { } }.orEmpty() }.distinctUntilChanged() - .doOnNext { Timber.d("RX: memberIds emitted. Size: ${it.size}") } + .doOnNext { Timber.v("RX: memberIds emitted. Size: ${it.size}") } // Observe the device info of the users in the room val cryptoDeviceInfoObservable = memberIdsChangeObservable @@ -68,9 +68,9 @@ class RxRoom(private val room: Room, private val session: Session) { membersIds } .startWith(membersIds) - .doOnNext { Timber.d("RX: CryptoDeviceInfo emitted. Size: ${it.size}") } + .doOnNext { Timber.v("RX: CryptoDeviceInfo emitted. Size: ${it.size}") } } - .doOnNext { Timber.d("RX: cryptoDeviceInfo emitted 2. Size: ${it.size}") } + .doOnNext { Timber.v("RX: cryptoDeviceInfo emitted 2. Size: ${it.size}") } val roomEncryptionTrustLevelObservable = cryptoDeviceInfoObservable .map { userIds -> @@ -80,7 +80,7 @@ class RxRoom(private val room: Room, private val session: Session) { session.getCrossSigningService().getTrustLevelForUsers(userIds).toOptional() } } - .doOnNext { Timber.d("RX: roomEncryptionTrustLevel emitted: ${it.getOrNull()?.name}") } + .doOnNext { Timber.v("RX: roomEncryptionTrustLevel emitted: ${it.getOrNull()?.name}") } return Observable .combineLatest, Optional, Optional>( @@ -92,18 +92,18 @@ class RxRoom(private val room: Room, private val session: Session) { ).toOptional() } ) - .doOnNext { Timber.d("RX: final room summary emitted for ${it.getOrNull()?.roomId}") } + .doOnNext { Timber.v("RX: final room summary emitted for ${it.getOrNull()?.roomId}") } } fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable> { val roomMembersObservable = room.getRoomMembersLive(queryParams).asObservable() .startWith(room.getRoomMembers(queryParams)) - .doOnNext { Timber.d("RX: room members emitted. Size: ${it.size}") } + .doOnNext { Timber.v("RX: room members emitted. Size: ${it.size}") } // TODO Do it only for room members of the room (switchMap) val cryptoDeviceInfoObservable = session.getLiveCryptoDeviceInfo().asObservable() .startWith(emptyList()) - .doOnNext { Timber.d("RX: cryptoDeviceInfo emitted. Size: ${it.size}") } + .doOnNext { Timber.v("RX: cryptoDeviceInfo emitted. Size: ${it.size}") } return Observable .combineLatest, List, List>( @@ -122,7 +122,7 @@ class RxRoom(private val room: Room, private val session: Session) { } } ) - .doOnNext { Timber.d("RX: final room members emitted. Size: ${it.size}") } + .doOnNext { Timber.v("RX: final room members emitted. Size: ${it.size}") } } fun liveAnnotationSummary(eventId: String): Observable> { diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 1f5ff9422c..88f8e82843 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -41,11 +41,11 @@ class RxSession(private val session: Session) { fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Observable> { val summariesObservable = session.getRoomSummariesLive(queryParams).asObservable() .startWith(session.getRoomSummaries(queryParams)) - .doOnNext { Timber.d("RX: summaries emitted: size: ${it.size}") } + .doOnNext { Timber.v("RX: summaries emitted: size: ${it.size}") } val cryptoDeviceInfoObservable = session.getLiveCryptoDeviceInfo().asObservable() .startWith(emptyList()) - .doOnNext { Timber.d("RX: crypto device info emitted: size: ${it.size}") } + .doOnNext { Timber.v("RX: crypto device info emitted: size: ${it.size}") } return Observable .combineLatest, List, List>( diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt index f15c5bb1ad..5519e5b7ac 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt @@ -57,6 +57,7 @@ internal class MXMegolmDecryption(private val userId: String, var newSessionListener: NewSessionListener? = null + var hasCheckUserCrossSigning = false /** * Events which we couldn't decrypt due to unknown sessions / indexes: map from * senderKey|sessionId to timelines to list of MatrixEvents. @@ -65,6 +66,11 @@ internal class MXMegolmDecryption(private val userId: String, override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult { // If cross signing is enabled, we don't send request until the keys are trusted + // There could be a race effect here when xsigning is enabled, we should ensure that keys was downloaded once + if (!hasCheckUserCrossSigning) { + deviceListManager.downloadKeys(listOf(userId), true) + hasCheckUserCrossSigning = true + } val requestOnFail = if (cryptoStore.getMyCrossSigningInfo() != null) { cryptoStore.getMyCrossSigningInfo()?.isTrusted() == true diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt index 70eadb550a..def7f2c2f7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationTask.kt @@ -131,8 +131,7 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( EventType.KEY_VERIFICATION_ACCEPT, EventType.KEY_VERIFICATION_START, EventType.KEY_VERIFICATION_MAC, - // TODO Add ? - // EventType.KEY_VERIFICATION_READY, + EventType.KEY_VERIFICATION_READY, EventType.KEY_VERIFICATION_KEY -> { Timber.v("## SAS REF in room $roomId for event ${event.eventId}") event.content.toModel()?.relatesTo?.let { @@ -161,8 +160,7 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( EventType.KEY_VERIFICATION_ACCEPT, EventType.KEY_VERIFICATION_START, EventType.KEY_VERIFICATION_MAC, - // TODO Add ? - // EventType.KEY_VERIFICATION_READY, + EventType.KEY_VERIFICATION_READY, EventType.KEY_VERIFICATION_KEY -> { Timber.v("## SAS REF in room $roomId for event ${event.eventId}") encryptedEventContent.relatesTo.eventId?.let { @@ -461,6 +459,9 @@ internal class DefaultEventRelationsAggregationTask @Inject constructor( EventType.KEY_VERIFICATION_ACCEPT -> { updateVerificationState(currentState, VerificationState.WAITING) } + EventType.KEY_VERIFICATION_READY -> { + updateVerificationState(currentState, VerificationState.WAITING) + } EventType.KEY_VERIFICATION_KEY -> { updateVerificationState(currentState, VerificationState.WAITING) } diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileActionItem.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileActionItem.kt index 9816a480e2..27586fcfde 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileActionItem.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileActionItem.kt @@ -16,11 +16,13 @@ package im.vector.riotx.core.epoxy.profiles +import android.content.res.ColorStateList import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat import androidx.core.view.isVisible +import androidx.core.widget.ImageViewCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R @@ -68,13 +70,20 @@ abstract class ProfileActionItem : VectorEpoxyModel() holder.subtitle.setTextOrHide(subtitle) if (iconRes != 0) { holder.icon.setImageResource(iconRes) + ImageViewCompat.setImageTintList(holder.icon, ColorStateList.valueOf(tintColor)) holder.icon.isVisible = true } else { holder.icon.isVisible = false } if (editableRes != 0) { + val tintColorSecondary = if (destructive) { + tintColor + } else { + ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary) + } holder.editable.setImageResource(editableRes) + ImageViewCompat.setImageTintList(holder.editable, ColorStateList.valueOf(tintColorSecondary)) holder.editable.isVisible = true } else { holder.editable.isVisible = false diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileItemExtensions.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileItemExtensions.kt index 7dce5e15d3..beea3ca620 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileItemExtensions.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileItemExtensions.kt @@ -46,9 +46,7 @@ fun EpoxyController.buildProfileAction( id("action_$id") subtitle(subtitle) editable(editable) - apply { - editableRes?.let { editableRes(editableRes) } - } + editableRes?.let { editableRes(editableRes) } destructive(destructive) title(title) listener { _ -> diff --git a/vector/src/main/java/im/vector/riotx/features/settings/crosssigning/CrossSigningSettingsFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/crosssigning/CrossSigningSettingsFragment.kt index 84be3ade8a..97e9d6d923 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/crosssigning/CrossSigningSettingsFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/crosssigning/CrossSigningSettingsFragment.kt @@ -15,8 +15,9 @@ */ package im.vector.riotx.features.settings.crosssigning +import android.content.DialogInterface import android.os.Bundle -import android.text.InputType +import android.view.KeyEvent import android.view.View import android.widget.EditText import androidx.appcompat.app.AlertDialog @@ -31,6 +32,7 @@ import im.vector.riotx.core.extensions.configureWith import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.platform.VectorBaseFragment +import im.vector.riotx.core.utils.toast import kotlinx.android.synthetic.main.fragment_generic_recycler.* import javax.inject.Inject @@ -91,27 +93,35 @@ class CrossSigningSettingsFragment @Inject constructor( } private fun requestPassword(sessionId: String) { - // Ask for password - val inflater = this.layoutInflater - val layout = inflater.inflate(R.layout.dialog_base_edit_text, null) + val inflater = requireActivity().layoutInflater + val layout = inflater.inflate(R.layout.dialog_prompt_password, null) + val passwordEditText = layout.findViewById(R.id.prompt_password) - val input = layout.findViewById(R.id.edit_text).also { - it.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD - } - - AlertDialog.Builder(requireContext()) - .setTitle("Confirm password") + AlertDialog.Builder(requireActivity()) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.devices_delete_dialog_title) .setView(layout) - .setPositiveButton(R.string.ok) { _, _ -> - val pass = input.text.toString() + .setPositiveButton(R.string.auth_submit, DialogInterface.OnClickListener { _, _ -> + if (passwordEditText.toString().isEmpty()) { + requireActivity().toast(R.string.error_empty_field_your_password) + return@OnClickListener + } + val pass = passwordEditText.text.toString() // TODO sessionId should never get out the ViewModel viewModel.handle(CrossSigningAction.InitializeCrossSigning(UserPasswordAuth( session = sessionId, password = pass ))) - } + }) .setNegativeButton(R.string.cancel, null) + .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> + if (event.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { + dialog.cancel() + return@OnKeyListener true + } + false + }) .show() } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/devices/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/devices/VectorSettingsDevicesFragment.kt index e9226773a1..c3d389f43a 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/devices/VectorSettingsDevicesFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/devices/VectorSettingsDevicesFragment.kt @@ -168,8 +168,8 @@ class VectorSettingsDevicesFragment @Inject constructor( viewModel.handle(DevicesAction.Password(mAccountPassword)) } else { val inflater = requireActivity().layoutInflater - val layout = inflater.inflate(R.layout.dialog_device_delete, null) - val passwordEditText = layout.findViewById(R.id.delete_password) + val layout = inflater.inflate(R.layout.dialog_prompt_password, null) + val passwordEditText = layout.findViewById(R.id.prompt_password) AlertDialog.Builder(requireActivity()) .setIcon(android.R.drawable.ic_dialog_alert) diff --git a/vector/src/main/res/layout/dialog_device_delete.xml b/vector/src/main/res/layout/dialog_prompt_password.xml similarity index 97% rename from vector/src/main/res/layout/dialog_device_delete.xml rename to vector/src/main/res/layout/dialog_prompt_password.xml index 7c905f3977..6315f20373 100644 --- a/vector/src/main/res/layout/dialog_device_delete.xml +++ b/vector/src/main/res/layout/dialog_prompt_password.xml @@ -31,7 +31,7 @@ android:textStyle="bold" />