From bb5179140c6f76b552f8281913e80de2106e8269 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 24 Jan 2020 09:14:32 +0100 Subject: [PATCH] Update profile screen for xSigning --- .../java/im/vector/matrix/rx/RxSession.kt | 5 ++ .../api/session/crypto/CryptoService.kt | 4 + .../android/internal/crypto/CryptoModule.kt | 59 +++++++++++++- .../internal/crypto/DefaultCryptoService.kt | 9 +++ .../internal/crypto/store/IMXCryptoStore.kt | 4 + .../crypto/store/db/RealmCryptoStore.kt | 29 +++++++ .../core/epoxy/profiles/ProfileActionItem.kt | 15 +++- .../epoxy/profiles/ProfileItemExtensions.kt | 14 +++- .../riotx/core/ui/list/GenericFooterItem.kt | 5 ++ .../home/room/detail/RoomDetailFragment.kt | 3 +- .../RoomMemberProfileController.kt | 78 ++++++++++++++++--- .../RoomMemberProfileViewModel.kt | 21 +++++ .../RoomMemberProfileViewState.kt | 8 +- .../main/res/layout/item_profile_action.xml | 1 - vector/src/main/res/values/strings_riotX.xml | 7 +- 15 files changed, 237 insertions(+), 25 deletions(-) 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 406e274258..383a2ccb63 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 @@ -29,6 +29,7 @@ import im.vector.matrix.android.api.session.user.model.User import im.vector.matrix.android.api.util.JsonDict import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.api.util.toOptional +import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo import io.reactivex.Observable import io.reactivex.Single @@ -98,6 +99,10 @@ class RxSession(private val session: Session) { fun getProfileInfo(userId: String): Single = singleBuilder { session.getProfile(userId, it) } + + fun liveUserCryptoDevices(userId: String) : Observable> { + return session.getLiveCryptoDeviceInfo(userId).asObservable() + } } fun Session.rx(): RxSession { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt index 2b1e92c317..38dd6399b1 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.api.session.crypto import android.content.Context +import androidx.lifecycle.LiveData import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.listeners.ProgressListener import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService @@ -117,6 +118,9 @@ interface CryptoService { fun downloadKeys(userIds: List, forceDownload: Boolean, callback: MatrixCallback>) + fun getCryptoDeviceInfo(userId: String) : List + fun getLiveCryptoDeviceInfo(userId: String) : LiveData> + fun addNewSessionListener(newSessionListener: NewSessionListener) fun removeSessionListener(listener: NewSessionListener) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt index 9974f597cd..4e0cf5f6af 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoModule.kt @@ -16,6 +16,7 @@ package im.vector.matrix.android.internal.crypto +import com.zhuinden.monarchy.Monarchy import dagger.Binds import dagger.Module import dagger.Provides @@ -25,12 +26,64 @@ import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningServ import im.vector.matrix.android.internal.crypto.api.CryptoApi import im.vector.matrix.android.internal.crypto.crosssigning.DefaultCrossSigningService import im.vector.matrix.android.internal.crypto.keysbackup.api.RoomKeysApi -import im.vector.matrix.android.internal.crypto.keysbackup.tasks.* +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultCreateKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteBackupTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultDeleteSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetKeysBackupLastVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultGetSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultStoreSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DefaultUpdateKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteBackupTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.DeleteSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetKeysBackupLastVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetKeysBackupVersionTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.GetSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreRoomSessionDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreSessionsDataTask +import im.vector.matrix.android.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreMigration import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule -import im.vector.matrix.android.internal.crypto.tasks.* +import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultClaimOneTimeKeysForUsersDevice +import im.vector.matrix.android.internal.crypto.tasks.DefaultDeleteDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultDeleteDeviceWithUserPasswordTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultDownloadKeysForUsers +import im.vector.matrix.android.internal.crypto.tasks.DefaultEncryptEventTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultGetDeviceInfoTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultGetDevicesTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultSendToDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultSendVerificationMessageTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultSetDeviceNameTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultUploadKeysTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultUploadSignaturesTask +import im.vector.matrix.android.internal.crypto.tasks.DefaultUploadSigningKeysTask +import im.vector.matrix.android.internal.crypto.tasks.DeleteDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.DeleteDeviceWithUserPasswordTask +import im.vector.matrix.android.internal.crypto.tasks.DownloadKeysForUsersTask +import im.vector.matrix.android.internal.crypto.tasks.EncryptEventTask +import im.vector.matrix.android.internal.crypto.tasks.GetDeviceInfoTask +import im.vector.matrix.android.internal.crypto.tasks.GetDevicesTask +import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask +import im.vector.matrix.android.internal.crypto.tasks.SendVerificationMessageTask +import im.vector.matrix.android.internal.crypto.tasks.SetDeviceNameTask +import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask +import im.vector.matrix.android.internal.crypto.tasks.UploadSignaturesTask +import im.vector.matrix.android.internal.crypto.tasks.UploadSigningKeysTask import im.vector.matrix.android.internal.database.RealmKeysUtils import im.vector.matrix.android.internal.di.CryptoDatabase import im.vector.matrix.android.internal.di.SessionFilesDirectory @@ -203,5 +256,5 @@ internal abstract class CryptoModule { : DeleteDeviceWithUserPasswordTask @Binds - abstract fun bindCrossSigningService(crossSigningService: DefaultCrossSigningService) : CrossSigningService + abstract fun bindCrossSigningService(crossSigningService: DefaultCrossSigningService): CrossSigningService } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt index ffc8ba69d8..b2a860e6d5 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt @@ -21,6 +21,7 @@ package im.vector.matrix.android.internal.crypto import android.content.Context import android.os.Handler import android.os.Looper +import androidx.lifecycle.LiveData import com.squareup.moshi.Types import com.zhuinden.monarchy.Monarchy import dagger.Lazy @@ -154,6 +155,7 @@ internal class DefaultCryptoService @Inject constructor( private val cryptoCoroutineScope: CoroutineScope ) : CryptoService { + init { sasVerificationService.cryptoService = this } @@ -397,6 +399,13 @@ internal class DefaultCryptoService @Inject constructor( null } } + override fun getCryptoDeviceInfo(userId: String): List { + return cryptoStore.getUserDevices(userId)?.map { it.value } ?: emptyList() + } + + override fun getLiveCryptoDeviceInfo(userId: String): LiveData> { + return cryptoStore.getLiveDeviceList(userId) + } /** * Set the devices as known diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt index 7236881954..35947cc692 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.internal.crypto.store +import androidx.lifecycle.LiveData import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest import im.vector.matrix.android.internal.crypto.NewSessionListener @@ -195,6 +196,9 @@ internal interface IMXCryptoStore { */ fun getUserDevices(userId: String): Map? + fun getUserDeviceList(userId: String): List? + + fun getLiveDeviceList(userId: String): LiveData> /** * Store the crypto algorithm for a room. * diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt index ca44a18fa4..48ec16b00e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt @@ -16,6 +16,9 @@ package im.vector.matrix.android.internal.crypto.store.db +import androidx.lifecycle.LiveData +import androidx.lifecycle.Transformations +import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest @@ -96,6 +99,10 @@ internal class RealmCryptoStore(private val realmConfiguration: RealmConfigurati newSessionListeners.remove(listener) } + private val monarchy = Monarchy.Builder() + .setRealmConfiguration(realmConfiguration) + .build() + /* ========================================================================================== * Other data * ========================================================================================== */ @@ -343,6 +350,28 @@ internal class RealmCryptoStore(private val realmConfiguration: RealmConfigurati ?.associateBy { it.deviceId } } + override fun getUserDeviceList(userId: String): List? { + return doRealmQueryAndCopy(realmConfiguration) { + it.where() + .equalTo(UserEntityFields.USER_ID, userId) + .findFirst() + } + ?.devices + ?.map { CryptoMapper.mapToModel(it) } + } + + override fun getLiveDeviceList(userId: String): LiveData> { + val liveData = monarchy.findAllMappedWithChanges( + { realm: Realm -> realm.where().equalTo(UserEntityFields.USER_ID, userId) }, + { entity -> + entity.devices.map { CryptoMapper.mapToModel(it) } + } + ) + return Transformations.map(liveData) { + it.firstOrNull() ?: emptyList() + } + } + override fun storeRoomAlgorithm(roomId: String, algorithm: String) { doRealmTransaction(realmConfiguration) { CryptoRoomEntity.getOrCreate(it, roomId).algorithm = algorithm 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 0a7dcb0de7..fa15fee77f 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 @@ -38,12 +38,18 @@ abstract class ProfileActionItem : VectorEpoxyModel() var subtitle: String? = null @EpoxyAttribute var iconRes: Int = 0 + + @EpoxyAttribute + var editableRes: Int = R.drawable.ic_arrow_right + @EpoxyAttribute var editable: Boolean = true + @EpoxyAttribute var destructive: Boolean = false + @EpoxyAttribute - lateinit var listener: View.OnClickListener + var listener: View.OnClickListener? = null override fun bind(holder: Holder) { super.bind(holder) @@ -63,6 +69,13 @@ abstract class ProfileActionItem : VectorEpoxyModel() } else { holder.icon.isVisible = false } + + if (editableRes != 0) { + holder.editable.setImageResource(editableRes) + holder.editable.isVisible = true + } else { + holder.editable.isVisible = false + } } class Holder : VectorEpoxyHolder() { 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 32060f577d..511dca9c8c 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 @@ -35,19 +35,27 @@ fun EpoxyController.buildProfileAction( subtitle: String? = null, editable: Boolean = true, @DrawableRes icon: Int = 0, + @DrawableRes editableRes: Int? = null, destructive: Boolean = false, divider: Boolean = true, - action: () -> Unit + action: (() -> Unit)? = null ) { profileActionItem { iconRes(icon) id("action_$id") subtitle(subtitle) editable(editable) + apply { + editableRes?.let { editableRes(editableRes) } + } destructive(destructive) title(title) - listener { _ -> - action() + apply { + action?.let { + listener { _ -> + it() + } + } } } diff --git a/vector/src/main/java/im/vector/riotx/core/ui/list/GenericFooterItem.kt b/vector/src/main/java/im/vector/riotx/core/ui/list/GenericFooterItem.kt index 02869fa420..a2ed4ba851 100644 --- a/vector/src/main/java/im/vector/riotx/core/ui/list/GenericFooterItem.kt +++ b/vector/src/main/java/im/vector/riotx/core/ui/list/GenericFooterItem.kt @@ -15,6 +15,7 @@ */ package im.vector.riotx.core.ui.list +import android.view.Gravity import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass @@ -41,12 +42,16 @@ abstract class GenericFooterItem : VectorEpoxyModel() @EpoxyAttribute var itemClickAction: GenericItem.Action? = null + @EpoxyAttribute + var centered: Boolean = true + override fun bind(holder: Holder) { holder.text.setTextOrHide(text) when (style) { GenericItem.STYLE.BIG_TEXT -> holder.text.textSize = 18f GenericItem.STYLE.NORMAL_TEXT -> holder.text.textSize = 14f } + holder.text.gravity = if(centered) Gravity.CENTER_HORIZONTAL else Gravity.START holder.view.setOnClickListener { itemClickAction?.perform?.run() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 688699c9af..236dd19030 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -1027,8 +1027,7 @@ class RoomDetailFragment @Inject constructor( } override fun onAvatarClicked(informationData: MessageInformationData) { - // DO NOT COMMIT openRoomMemberProfile(informationData.senderId) - roomDetailViewModel.handle(RoomDetailAction.RequestVerification(informationData.senderId)) + openRoomMemberProfile(informationData.senderId) } private fun openRoomMemberProfile(userId: String) { diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileController.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileController.kt index 23c713068a..87cf1d730a 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileController.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileController.kt @@ -23,6 +23,7 @@ import im.vector.riotx.core.epoxy.profiles.buildProfileAction import im.vector.riotx.core.epoxy.profiles.buildProfileSection import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.resources.StringProvider +import im.vector.riotx.core.ui.list.genericFooterItem import javax.inject.Inject class RoomMemberProfileController @Inject constructor( @@ -70,20 +71,73 @@ class RoomMemberProfileController @Inject constructor( private fun buildRoomMemberActions(state: RoomMemberProfileViewState) { // Security buildProfileSection(stringProvider.getString(R.string.room_profile_section_security)) - val learnMoreSubtitle = if (state.isRoomEncrypted) { - R.string.room_profile_encrypted_subtitle + + if (state.isRoomEncrypted) { + if (state.userMXCrossSigningInfo != null) { + // Cross signing is enabled for this user + if (state.userMXCrossSigningInfo.isTrusted) { + //User is trusted + val icon = if (state.allDevicesAreTrusted.invoke() == true) R.drawable.ic_shield_trusted + else R.drawable.ic_shield_warning + + val titleRes = if (state.allDevicesAreTrusted.invoke() == true) R.string.verification_profile_verified + else R.string.verification_profile_warning + + buildProfileAction( + id = "learn_more", + title = stringProvider.getString(titleRes), + dividerColor = dividerColor, + editable = true, + icon = icon, + divider = false, + action = { callback?.onLearnMoreClicked() } + ) + } else { + //Not trusted, propose to verify + if (!state.isMine) { + buildProfileAction( + id = "learn_more", + title = stringProvider.getString(R.string.verification_profile_verify), + dividerColor = dividerColor, + editable = true, + icon = R.drawable.ic_shield_black, + divider = false, + action = { callback?.onLearnMoreClicked() } + ) + } + + genericFooterItem { + id("verify_footer") + text(stringProvider.getString(R.string.room_profile_encrypted_subtitle)) + centered(false) + } + } + } else { + buildProfileAction( + id = "learn_more", + title = stringProvider.getString(R.string.room_profile_section_security_learn_more), + dividerColor = dividerColor, + editable = false, + divider = false, + subtitle = stringProvider.getString(R.string.room_profile_encrypted_subtitle), + action = { callback?.onLearnMoreClicked() } + ) + } } else { - R.string.room_profile_not_encrypted_subtitle +// buildProfileAction( +// id = "learn_more", +// title = stringProvider.getString(R.string.room_profile_section_security_learn_more), +// dividerColor = dividerColor, +// editable = false, +// divider = false, +// subtitle = stringProvider.getString(R.string.room_profile_not_encrypted_subtitle) +// ) + genericFooterItem { + id("verify_footer_not_encrypted") + text(stringProvider.getString(R.string.room_profile_not_encrypted_subtitle)) + centered(false) + } } - buildProfileAction( - id = "learn_more", - title = stringProvider.getString(R.string.room_profile_section_security_learn_more), - dividerColor = dividerColor, - editable = false, - divider = false, - subtitle = stringProvider.getString(learnMoreSubtitle), - action = { callback?.onLearnMoreClicked() } - ) // More if (!state.isMine) { diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt index 88f394e865..29814491a3 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -42,6 +42,7 @@ import im.vector.matrix.rx.mapOptional import im.vector.matrix.rx.rx import im.vector.matrix.rx.unwrap import im.vector.riotx.R +import im.vector.riotx.core.di.HasScreenInjector import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.utils.DataSource @@ -69,6 +70,17 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v val fragment: RoomMemberProfileFragment = (viewModelContext as FragmentViewModelContext).fragment() return fragment.viewModelFactory.create(state) } + + override fun initialState(viewModelContext: ViewModelContext): RoomMemberProfileViewState? { + val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession() + val args = viewModelContext.args() + + return RoomMemberProfileViewState( + userId = args.userId, + roomId = args.roomId, + userMXCrossSigningInfo = session.getCrossSigningService().getUserCrossSigningKeys(args.userId) + ) + } } private val _viewEvents = PublishDataSource() @@ -97,6 +109,14 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v observeRoomMemberSummary(room) observeRoomSummaryAndPowerLevels(room) } + + session.rx().liveUserCryptoDevices(initialState.userId) + .map { + it.fold(true, { prev, dev -> prev && dev.isVerified}) + } + .execute { + copy(allDevicesAreTrusted = it) + } } } @@ -143,6 +163,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v .execute { copy(userMatrixItem = it) } + } private fun observeRoomSummaryAndPowerLevels(room: Room) { diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewState.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewState.kt index ba079e9996..d4fa73c0b7 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewState.kt @@ -20,8 +20,10 @@ package im.vector.riotx.features.roommemberprofile import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized +import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo import im.vector.matrix.android.api.session.room.model.PowerLevelsContent import im.vector.matrix.android.api.util.MatrixItem +import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo data class RoomMemberProfileViewState( val userId: String, @@ -32,8 +34,10 @@ data class RoomMemberProfileViewState( val isRoomEncrypted: Boolean = false, val powerLevelsContent: Async = Uninitialized, val userPowerLevelString: Async = Uninitialized, - val userMatrixItem: Async = Uninitialized + val userMatrixItem: Async = Uninitialized, + val userMXCrossSigningInfo: MXCrossSigningInfo? = null, + val allDevicesAreTrusted: Async = Uninitialized ) : MvRxState { - constructor(args: RoomMemberProfileArgs) : this(roomId = args.roomId, userId = args.userId) + //constructor(args: RoomMemberProfileArgs) : this(roomId = args.roomId, userId = args.userId) } diff --git a/vector/src/main/res/layout/item_profile_action.xml b/vector/src/main/res/layout/item_profile_action.xml index 2e32b4b444..a2499f2e83 100644 --- a/vector/src/main/res/layout/item_profile_action.xml +++ b/vector/src/main/res/layout/item_profile_action.xml @@ -20,7 +20,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:scaleType="center" - android:tint="?riotx_text_secondary" android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 5faa105ec0..5803157c6d 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -55,7 +55,7 @@ Waiting for %s… For extra security, verify %s by checking a one-time code on both your devices.\n\nFor maximum security, do this in person. Messages in this room are not end-to-end encrypted. - Messages in this room are end-to-end encrypted. + Messages in this room are end-to-end encrypted.\n\nYour messages are secured with locks and only you and the recipient have the unique keys to unlock them. Security Learn more More @@ -119,4 +119,9 @@ %d active sessions + + Verify + Verified + Warning +