diff --git a/CHANGES.md b/CHANGES.md index 5daced2228..3978038b8d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ Improvements 🙌: - Set up SSSS from security settings (#1567) - New lab setting to add 'unread notifications' tab to main screen - Render third party invite event (#548) + - Display three pid invites in the room members list (#548) Bugfix 🐛: - Integration Manager: Wrong URL to review terms if URL in config contains path (#1606) 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 2e96863d60..e945a52650 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 @@ -72,6 +72,13 @@ class RxRoom(private val room: Room) { } } + fun liveStateEvents(eventTypes: Set): Observable> { + return room.getStateEventsLive(eventTypes).asObservable() + .startWithCallable { + room.getStateEvents(eventTypes) + } + } + fun liveReadMarker(): Observable> { return room.getReadMarkerLive().asObservable() } diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileMatrixItem.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileMatrixItem.kt index e9f4dba7a5..d6629c708e 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileMatrixItem.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/profiles/ProfileMatrixItem.kt @@ -42,7 +42,10 @@ abstract class ProfileMatrixItem : VectorEpoxyModel() override fun bind(holder: Holder) { super.bind(holder) val bestName = matrixItem.getBestName() - val matrixId = matrixItem.id.takeIf { it != bestName } + val matrixId = matrixItem.id + .takeIf { it != bestName } + // Special case for ThreePid fake matrix item + .takeIf { it != "@" } holder.view.setOnClickListener(clickListener) holder.titleView.text = bestName holder.subtitleView.setTextOrHide(matrixId) diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListController.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListController.kt index d0939e939e..6dcf5a0bd3 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListController.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListController.kt @@ -17,7 +17,11 @@ package im.vector.riotx.features.roomprofile.members import com.airbnb.epoxy.TypedEpoxyController +import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.RoomMemberSummary +import im.vector.matrix.android.api.session.room.model.RoomThirdPartyInviteContent +import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.api.util.toMatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.dividerItem @@ -37,6 +41,7 @@ class RoomMemberListController @Inject constructor( interface Callback { fun onRoomMemberClicked(roomMember: RoomMemberSummary) + fun onThreePidInvites(event: Event) } private val dividerColor = colorProvider.getColorFromAttribute(R.attr.vctr_list_divider_color) @@ -76,5 +81,34 @@ class RoomMemberListController @Inject constructor( } ) } + buildThreePidInvites(data) + } + + private fun buildThreePidInvites(data: RoomMemberListViewState) { + if (data.threePidInvites().isNullOrEmpty()) { + return + } + + buildProfileSection( + stringProvider.getString(R.string.room_member_power_level_three_pid_invites) + ) + + data.threePidInvites()?.forEachIndexed { idx, event -> + val content = event.content.toModel() ?: return@forEachIndexed + + profileMatrixItem { + id("3pid_$idx") + matrixItem(content.toMatrixItem()) + avatarRenderer(avatarRenderer) + clickListener { _ -> + callback?.onThreePidInvites(event) + } + } + + } + } + + private fun RoomThirdPartyInviteContent.toMatrixItem(): MatrixItem { + return MatrixItem.UserItem("@", displayName = displayName) } } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListFragment.kt index 6bd2b5d0e3..72ec3e8462 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListFragment.kt @@ -23,6 +23,7 @@ import android.view.View import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState +import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.model.RoomMemberSummary import im.vector.matrix.android.api.util.toMatrixItem import im.vector.riotx.R @@ -88,6 +89,10 @@ class RoomMemberListFragment @Inject constructor( navigator.openRoomMemberProfile(roomMember.userId, roomId = roomProfileArgs.roomId, context = requireActivity()) } + override fun onThreePidInvites(event: Event) { + // TODO Display a bottom sheet to revoke invite if power level is high enough + } + private fun renderRoomSummary(state: RoomMemberListViewState) { state.roomSummary()?.let { roomSettingsToolbarTitleView.text = it.displayName diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt index f177d26725..e412e41b73 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewModel.kt @@ -68,6 +68,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState init { observeRoomMemberSummaries() + observeThirdPartyInvites() observeRoomSummary() observePowerLevel() } @@ -140,6 +141,13 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState } } + private fun observeThirdPartyInvites() { + room.rx().liveStateEvents(setOf(EventType.STATE_ROOM_THIRD_PARTY_INVITE)) + .execute { async -> + copy(threePidInvites = async) + } + } + private fun buildRoomMemberSummaries(powerLevelsContent: PowerLevelsContent, roomMembers: List): RoomMemberSummaries { val admins = ArrayList() val moderators = ArrayList() diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewState.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewState.kt index ece49a178c..6a8738b450 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/members/RoomMemberListViewState.kt @@ -21,6 +21,7 @@ import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel +import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.model.RoomMemberSummary import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.riotx.R @@ -30,6 +31,7 @@ data class RoomMemberListViewState( val roomId: String, val roomSummary: Async = Uninitialized, val roomMemberSummaries: Async = Uninitialized, + val threePidInvites: Async> = Uninitialized, val trustLevelMap: Async> = Uninitialized, val actionsPermissions: ActionPermissions = ActionPermissions() ) : MvRxState { diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 36ec74e028..62e27b51c2 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2148,6 +2148,7 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming Custom Invites Users + Other invites Admin in %1$s Moderator in %1$s