Skip to content

Commit

Permalink
Merge pull request #3631 from element-hq/feature/fga/rework_room_summary
Browse files Browse the repository at this point in the history
Rework room summary
  • Loading branch information
ganfra authored Oct 9, 2024
2 parents 47dcdef + 5afa7f6 commit a3db4b2
Show file tree
Hide file tree
Showing 70 changed files with 734 additions and 563 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.getRoomInfoFlow
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
import kotlinx.coroutines.flow.combine
Expand Down Expand Up @@ -120,12 +122,9 @@ class RoomFlowNode @AssistedInject constructor(
}

private fun subscribeToRoomInfoFlow(roomId: RoomId, serverNames: List<String>) {
val roomInfoFlow = client.getRoomInfoFlow(
roomId = roomId
).map { it.getOrNull() }

val isSpaceFlow = roomInfoFlow.map { it?.isSpace.orFalse() }.distinctUntilChanged()
val currentMembershipFlow = roomInfoFlow.map { it?.currentUserMembership }.distinctUntilChanged()
val roomInfoFlow = client.getRoomInfoFlow(roomIdOrAlias = roomId.toRoomIdOrAlias())
val isSpaceFlow = roomInfoFlow.map { it.getOrNull()?.isSpace.orFalse() }.distinctUntilChanged()
val currentMembershipFlow = roomInfoFlow.map { it.getOrNull()?.currentUserMembership }.distinctUntilChanged()
combine(currentMembershipFlow, isSpaceFlow) { membership, isSpace ->
Timber.d("Room membership: $membership")
when (membership) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.getRoomInfoFlow
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomType
Expand Down Expand Up @@ -70,7 +72,7 @@ class JoinRoomPresenter @AssistedInject constructor(
override fun present(): JoinRoomState {
val coroutineScope = rememberCoroutineScope()
var retryCount by remember { mutableIntStateOf(0) }
val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty())
val roomInfo by matrixClient.getRoomInfoFlow(roomId.toRoomIdOrAlias()).collectAsState(initial = Optional.empty())
val joinAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val knockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val contentState by produceState<ContentState>(
Expand Down Expand Up @@ -204,7 +206,7 @@ internal fun MatrixRoomInfo.toContentState(): ContentState {
name = name,
topic = topic,
alias = canonicalAlias,
numberOfMembers = activeMembersCount,
numberOfMembers = activeMembersCount.toLong(),
isDm = isDm,
roomType = if (isSpace) RoomType.Space else RoomType.Room,
roomAvatarUrl = avatarUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.room.RoomType
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.ui.model.InviteSender

open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_SERVER_LIST
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom
import io.element.android.libraries.matrix.ui.model.toInviteSender
import io.element.android.tests.testutils.WarmUpRule
Expand Down Expand Up @@ -67,10 +67,10 @@ class JoinRoomPresenterTest {

@Test
fun `present - when room is joined then content state is filled with his data`() = runTest {
val roomInfo = aRoomInfo()
val roomSummary = aRoomSummary()
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
getRoomSummaryFlowLambda = { _ ->
flowOf(Optional.of(roomSummary))
}
}
val presenter = createJoinRoomPresenter(
Expand All @@ -81,22 +81,22 @@ class JoinRoomPresenterTest {
awaitItem().also { state ->
val contentState = state.contentState as ContentState.Loaded
assertThat(contentState.roomId).isEqualTo(A_ROOM_ID)
assertThat(contentState.name).isEqualTo(roomInfo.name)
assertThat(contentState.topic).isEqualTo(roomInfo.topic)
assertThat(contentState.alias).isEqualTo(roomInfo.canonicalAlias)
assertThat(contentState.numberOfMembers).isEqualTo(roomInfo.activeMembersCount)
assertThat(contentState.isDm).isEqualTo(roomInfo.isDirect)
assertThat(contentState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl)
assertThat(contentState.name).isEqualTo(roomSummary.info.name)
assertThat(contentState.topic).isEqualTo(roomSummary.info.topic)
assertThat(contentState.alias).isEqualTo(roomSummary.info.canonicalAlias)
assertThat(contentState.numberOfMembers).isEqualTo(roomSummary.info.activeMembersCount)
assertThat(contentState.isDm).isEqualTo(roomSummary.info.isDirect)
assertThat(contentState.roomAvatarUrl).isEqualTo(roomSummary.info.avatarUrl)
}
}
}

@Test
fun `present - when room is invited then join authorization is equal to invited`() = runTest {
val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED)
val roomSummary = aRoomSummary(currentUserMembership = CurrentUserMembership.INVITED)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
getRoomSummaryFlowLambda = { _ ->
flowOf(Optional.of(roomSummary))
}
}
val presenter = createJoinRoomPresenter(
Expand All @@ -114,13 +114,13 @@ class JoinRoomPresenterTest {
fun `present - when room is invited then join authorization is equal to invited, an inviter is provided`() = runTest {
val inviter = aRoomMember(userId = UserId("@bob:example.com"), displayName = "Bob")
val expectedInviteSender = inviter.toInviteSender()
val roomInfo = aRoomInfo(
val roomSummary = aRoomSummary(
currentUserMembership = CurrentUserMembership.INVITED,
inviter = inviter,
)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
getRoomSummaryFlowLambda = { _ ->
flowOf(Optional.of(roomSummary))
}
}
val presenter = createJoinRoomPresenter(
Expand All @@ -140,10 +140,10 @@ class JoinRoomPresenterTest {
val acceptDeclinePresenter = Presenter {
anAcceptDeclineInviteState(eventSink = eventSinkRecorder)
}
val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED)
val roomSummary = aRoomSummary(currentUserMembership = CurrentUserMembership.INVITED)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
getRoomSummaryFlowLambda = { _ ->
flowOf(Optional.of(roomSummary))
}
}
val presenter = createJoinRoomPresenter(
Expand Down Expand Up @@ -224,10 +224,10 @@ class JoinRoomPresenterTest {

@Test
fun `present - when room is left and public then join authorization is equal to canJoin`() = runTest {
val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.LEFT, isPublic = true)
val roomSummary = aRoomSummary(currentUserMembership = CurrentUserMembership.LEFT, isPublic = true)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
getRoomSummaryFlowLambda = { _ ->
flowOf(Optional.of(roomSummary))
}
}
val presenter = createJoinRoomPresenter(
Expand All @@ -243,10 +243,10 @@ class JoinRoomPresenterTest {

@Test
fun `present - when room is left and not public then join authorization is equal to unknown`() = runTest {
val roomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.LEFT, isPublic = false)
val roomSummary = aRoomSummary(currentUserMembership = CurrentUserMembership.LEFT, isPublic = false)
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { _ ->
flowOf(Optional.of(roomInfo))
getRoomSummaryFlowLambda = { _ ->
flowOf(Optional.of(roomSummary))
}
}
val presenter = createJoinRoomPresenter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError
import io.element.android.features.messages.impl.draft.ComposerDraftService
import io.element.android.features.messages.impl.messagecomposer.suggestions.RoomAliasSuggestionsDataSource
import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsProcessor
import io.element.android.features.messages.impl.timeline.TimelineController
import io.element.android.features.messages.impl.utils.TextPillificationHelper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@
* Please see LICENSE in the repository root for full details.
*/

package io.element.android.features.messages.impl.messagecomposer
package io.element.android.features.messages.impl.messagecomposer.suggestions

import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject

data class RoomAliasSuggestion(
val roomAlias: RoomAlias,
val roomSummary: RoomSummary,
val roomId: RoomId,
val roomName: String?,
val roomAvatarUrl: String?,
)

interface RoomAliasSuggestionsDataSource {
Expand All @@ -32,14 +34,16 @@ class DefaultRoomAliasSuggestionsDataSource @Inject constructor(
override fun getAllRoomAliasSuggestions(): Flow<List<RoomAliasSuggestion>> {
return roomListService
.allRooms
.filteredSummaries
.summaries
.map { roomSummaries ->
roomSummaries
.mapNotNull { roomSummary ->
roomSummary.canonicalAlias?.let { roomAlias ->
roomSummary.info.canonicalAlias?.let { roomAlias ->
RoomAliasSuggestion(
roomAlias = roomAlias,
roomSummary = roomSummary,
roomId = roomSummary.roomId,
roomName = roomSummary.info.name,
roomAvatarUrl = roomSummary.info.avatarUrl,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.ui.components.aRoomSummaryDetails
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion
import kotlinx.collections.immutable.ImmutableList
Expand All @@ -60,7 +59,7 @@ fun SuggestionsPickerView(
when (suggestion) {
is ResolvedSuggestion.AtRoom -> "@room"
is ResolvedSuggestion.Member -> suggestion.roomMember.userId.value
is ResolvedSuggestion.Alias -> suggestion.roomSummary.roomId.value
is ResolvedSuggestion.Alias -> suggestion.roomId.value
}
}
) {
Expand Down Expand Up @@ -96,12 +95,12 @@ private fun SuggestionItemView(
val avatarData = when (suggestion) {
is ResolvedSuggestion.AtRoom -> roomAvatar?.copy(size = avatarSize) ?: AvatarData(roomId, roomName, null, avatarSize)
is ResolvedSuggestion.Member -> suggestion.roomMember.getAvatarData(avatarSize)
is ResolvedSuggestion.Alias -> suggestion.roomSummary.getAvatarData(avatarSize)
is ResolvedSuggestion.Alias -> suggestion.getAvatarData(avatarSize)
}
val title = when (suggestion) {
is ResolvedSuggestion.AtRoom -> stringResource(R.string.screen_room_mentions_at_room_title)
is ResolvedSuggestion.Member -> suggestion.roomMember.displayName
is ResolvedSuggestion.Alias -> suggestion.roomSummary.name
is ResolvedSuggestion.Alias -> suggestion.roomName
}
val subtitle = when (suggestion) {
is ResolvedSuggestion.AtRoom -> "@room"
Expand Down Expand Up @@ -152,11 +151,6 @@ internal fun SuggestionsPickerViewPreview() {
role = RoomMember.Role.USER,
)
val anAlias = remember { RoomAlias("#room:domain.org") }
val roomSummaryDetails = remember {
aRoomSummaryDetails(
name = "My room",
)
}
SuggestionsPickerView(
roomId = RoomId("!room:matrix.org"),
roomName = "Room",
Expand All @@ -166,8 +160,10 @@ internal fun SuggestionsPickerViewPreview() {
ResolvedSuggestion.Member(roomMember),
ResolvedSuggestion.Member(roomMember.copy(userId = UserId("@bob:server.org"), displayName = "Bob")),
ResolvedSuggestion.Alias(
anAlias,
roomSummaryDetails,
roomAlias = anAlias,
roomId = RoomId("!room:matrix.org"),
roomName = "My room",
roomAvatarUrl = null,
)
),
onSelectSuggestion = {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

package io.element.android.features.messages.impl.messagecomposer.suggestions

import io.element.android.features.messages.impl.messagecomposer.RoomAliasSuggestion
import io.element.android.libraries.core.data.filterUpTo
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
Expand Down Expand Up @@ -55,7 +54,14 @@ class SuggestionsProcessor @Inject constructor() {
SuggestionType.Room -> {
roomAliasSuggestions
.filter { it.roomAlias.value.contains(suggestion.text, ignoreCase = true) }
.map { ResolvedSuggestion.Alias(it.roomAlias, it.roomSummary) }
.map {
ResolvedSuggestion.Alias(
roomAlias = it.roomAlias,
roomId = it.roomId,
roomName = it.roomName,
roomAvatarUrl = it.roomAvatarUrl,
)
}
}
SuggestionType.Command,
is SuggestionType.Custom -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ package io.element.android.features.messages.impl.messagecomposer

import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.messages.impl.messagecomposer.suggestions.DefaultRoomAliasSuggestionsDataSource
import io.element.android.features.messages.impl.messagecomposer.suggestions.RoomAliasSuggestion
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
import io.element.android.libraries.matrix.test.room.aRoomSummary
Expand Down Expand Up @@ -38,7 +40,9 @@ class DefaultRoomAliasSuggestionsDataSourceTest {
listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
roomSummary = aRoomSummaryWithAnAlias
roomId = aRoomSummaryWithAnAlias.roomId,
roomName = aRoomSummaryWithAnAlias.info.name,
roomAvatarUrl = aRoomSummaryWithAnAlias.info.avatarUrl
)
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

package io.element.android.features.messages.impl.messagecomposer

import io.element.android.features.messages.impl.messagecomposer.suggestions.RoomAliasSuggestion
import io.element.android.features.messages.impl.messagecomposer.suggestions.RoomAliasSuggestionsDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow

Expand Down
Loading

0 comments on commit a3db4b2

Please sign in to comment.