From 11e4ee34edccccebdf88eba1755111fc48a46066 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 13:10:25 +0200 Subject: [PATCH] Use heroes to render room avatars --- .../EditDefaultNotificationSettingView.kt | 14 ++++++++++++-- .../roomdetails/impl/RoomDetailsPresenter.kt | 2 ++ .../roomdetails/impl/RoomDetailsState.kt | 3 +++ .../impl/RoomDetailsStateProvider.kt | 4 ++++ .../roomdetails/impl/RoomDetailsView.kt | 15 +++++++++++++-- .../datasource/RoomListRoomSummaryFactory.kt | 13 ++++++++++++- .../impl/model/RoomListRoomSummary.kt | 2 ++ .../impl/model/RoomListRoomSummaryProvider.kt | 3 +++ .../components/avatar/CompositeAvatar.kt | 2 +- .../matrix/ui/components/SelectedRoom.kt | 19 +++++++++++++++++-- .../roomselect/impl/RoomSelectView.kt | 12 ++++++++++-- 11 files changed, 79 insertions(+), 10 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt index f13aa90c4d..aac1ae94a8 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt @@ -25,9 +25,9 @@ import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.preferences.impl.R import io.element.android.libraries.designsystem.components.async.AsyncActionView -import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.CompositeAvatar import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferencePage @@ -114,7 +114,17 @@ fun EditDefaultNotificationSettingView( Text(text = subtitle) }, leadingContent = ListItemContent.Custom { - Avatar(avatarData = avatarData) + CompositeAvatar( + avatarData = avatarData, + heroes = summary.details.heroes.map { user -> + AvatarData( + id = user.userId.value, + name = user.displayName, + url = user.avatarUrl, + size = AvatarSize.CustomRoomNotificationSetting, + ) + } + ) }, onClick = { openRoomNotificationSettings(summary.details.roomId) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 966dade2c3..3d07ea3e63 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -49,6 +49,7 @@ import io.element.android.libraries.matrix.ui.room.getDirectRoomMember import io.element.android.libraries.matrix.ui.room.isOwnUserAdmin import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -151,6 +152,7 @@ class RoomDetailsPresenter @Inject constructor( isFavorite = isFavorite, displayRolesAndPermissionsSettings = !room.isDm && isUserAdmin, isPublic = isPublic, + heroes = roomInfo?.heroes.orEmpty().toPersistentList(), eventSink = ::handleEvents, ) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index aee1694e93..787aa79741 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -23,6 +23,8 @@ 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.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import io.element.android.libraries.matrix.api.user.MatrixUser +import kotlinx.collections.immutable.ImmutableList data class RoomDetailsState( val roomId: RoomId, @@ -43,6 +45,7 @@ data class RoomDetailsState( val isFavorite: Boolean, val displayRolesAndPermissionsSettings: Boolean, val isPublic: Boolean, + val heroes: ImmutableList, val eventSink: (RoomDetailsEvent) -> Unit ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index f970b80d82..84b1514c4b 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -28,6 +28,8 @@ import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import io.element.android.libraries.matrix.api.user.MatrixUser +import kotlinx.collections.immutable.toPersistentList open class RoomDetailsStateProvider : PreviewParameterProvider { override val values: Sequence @@ -99,6 +101,7 @@ fun aRoomDetailsState( isFavorite: Boolean = false, displayAdminSettings: Boolean = false, isPublic: Boolean = true, + heroes: List = emptyList(), eventSink: (RoomDetailsEvent) -> Unit = {}, ) = RoomDetailsState( roomId = roomId, @@ -119,6 +122,7 @@ fun aRoomDetailsState( isFavorite = isFavorite, displayRolesAndPermissionsSettings = displayAdminSettings, isPublic = isPublic, + heroes = heroes.toPersistentList(), eventSink = eventSink ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 078e1f6def..5fb78e1fe6 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -54,9 +54,9 @@ import io.element.android.features.userprofile.shared.blockuser.BlockUserDialogs import io.element.android.features.userprofile.shared.blockuser.BlockUserSection import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage import io.element.android.libraries.designsystem.components.ClickableLinkText -import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.CompositeAvatar import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.MainActionButton import io.element.android.libraries.designsystem.components.list.ListItemContent @@ -81,6 +81,7 @@ 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.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.getBestName +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -127,6 +128,7 @@ fun RoomDetailsView( roomAlias = state.roomAlias, isEncrypted = state.isEncrypted, isPublic = state.isPublic, + heroes = state.heroes, openAvatarPreview = { avatarUrl -> openAvatarPreview(state.roomName, avatarUrl) }, @@ -324,6 +326,7 @@ private fun RoomHeaderSection( roomAlias: RoomAlias?, isEncrypted: Boolean, isPublic: Boolean, + heroes: List = emptyList(), openAvatarPreview: (url: String) -> Unit, ) { Column( @@ -332,8 +335,16 @@ private fun RoomHeaderSection( .padding(horizontal = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Avatar( + CompositeAvatar( avatarData = AvatarData(roomId.value, roomName, avatarUrl, AvatarSize.RoomHeader), + heroes = heroes.map { user -> + AvatarData( + id = user.userId.value, + name = user.displayName, + url = user.avatarUrl, + size = AvatarSize.RoomHeader + ) + }, modifier = Modifier .size(70.dp) .clickable(enabled = avatarUrl != null) { openAvatarPreview(avatarUrl!!) } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt index 80232563ed..058573caf5 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt @@ -27,6 +27,8 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.ui.model.toInviteSender +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import javax.inject.Inject class RoomListRoomSummaryFactory @Inject constructor( @@ -54,6 +56,7 @@ class RoomListRoomSummaryFactory @Inject constructor( inviteSender = null, isDm = false, canonicalAlias = null, + heroes = persistentListOf(), ) } } @@ -90,7 +93,15 @@ class RoomListRoomSummaryFactory @Inject constructor( RoomSummaryDisplayType.INVITE } else { RoomSummaryDisplayType.ROOM - } + }, + heroes = roomSummary.details.heroes.map { + AvatarData( + id = it.userId.value, + name = it.displayName, + url = it.avatarUrl, + size = AvatarSize.RoomListItem, + ) + }.toImmutableList(), ) } } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt index 9afa6cd749..5e0bd5c65a 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt @@ -22,6 +22,7 @@ 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.room.RoomNotificationMode import io.element.android.libraries.matrix.ui.model.InviteSender +import kotlinx.collections.immutable.ImmutableList @Immutable data class RoomListRoomSummary( @@ -43,6 +44,7 @@ data class RoomListRoomSummary( val isDm: Boolean, val isFavorite: Boolean, val inviteSender: InviteSender?, + val heroes: ImmutableList, ) { val isHighlighted = userDefinedNotificationMode != RoomNotificationMode.MUTE && (numberOfUnreadNotifications > 0 || numberOfUnreadMentions > 0) || diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt index a39d50eac0..473c60049a 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt @@ -24,6 +24,7 @@ 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.RoomNotificationMode import io.element.android.libraries.matrix.ui.model.InviteSender +import kotlinx.collections.immutable.toImmutableList open class RoomListRoomSummaryProvider : PreviewParameterProvider { override val values: Sequence @@ -142,6 +143,7 @@ internal fun aRoomListRoomSummary( inviteSender: InviteSender? = null, displayType: RoomSummaryDisplayType = RoomSummaryDisplayType.ROOM, canonicalAlias: RoomAlias? = null, + heroes: List = emptyList(), ) = RoomListRoomSummary( id = id, roomId = RoomId(id), @@ -161,4 +163,5 @@ internal fun aRoomListRoomSummary( inviteSender = inviteSender, displayType = displayType, canonicalAlias = canonicalAlias, + heroes = heroes.toImmutableList(), ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/CompositeAvatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/CompositeAvatar.kt index df33f791a9..ada1671eea 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/CompositeAvatar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/CompositeAvatar.kt @@ -53,7 +53,7 @@ fun CompositeAvatar( } when (numberOfHeroes) { 0 -> { - // Cannot happen + error("Unsupported number of heroes: 0") } 1 -> { Avatar(heroes[0], modifier, contentDescription) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt index 7f8f9f2f56..a88ad47388 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt @@ -36,9 +36,9 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.CompositeAvatar import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Icon @@ -60,7 +60,22 @@ fun SelectedRoom( Column( horizontalAlignment = Alignment.CenterHorizontally, ) { - Avatar(AvatarData(roomSummary.roomId.value, roomSummary.name, roomSummary.avatarUrl, AvatarSize.SelectedRoom)) + CompositeAvatar( + avatarData = AvatarData( + roomSummary.roomId.value, + roomSummary.name, + roomSummary.avatarUrl, + AvatarSize.SelectedRoom, + ), + heroes = roomSummary.heroes.map { + AvatarData( + id = it.userId.value, + name = it.displayName, + url = it.avatarUrl, + size = AvatarSize.SelectedRoom + ) + } + ) Text( // If name is null, we do not have space to render "No room name", so just use `#` here. text = roomSummary.name ?: "#", diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt index fa8525bdc1..fce89c5c7e 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt @@ -41,9 +41,9 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.CompositeAvatar import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -221,13 +221,21 @@ private fun RoomSummaryView( .heightIn(56.dp), verticalAlignment = Alignment.CenterVertically ) { - Avatar( + CompositeAvatar( avatarData = AvatarData( id = summary.roomId.value, name = summary.name, url = summary.avatarUrl, size = AvatarSize.RoomSelectRoomListItem, ), + heroes = summary.heroes.map { + AvatarData( + it.userId.value, + it.displayName, + it.avatarUrl, + AvatarSize.RoomSelectRoomListItem, + ) + } ) Column( modifier = Modifier