From 3aed09ef4dd4d32874dcfee0b023e2b4a2d4eb19 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 19 Jun 2024 18:18:59 +0200 Subject: [PATCH 01/19] Map RoomHero to MatrixRoomInfo. --- .../libraries/matrix/api/room/MatrixRoomInfo.kt | 4 +++- .../matrix/impl/room/MatrixRoomInfoMapper.kt | 14 +++++++++++++- .../libraries/matrix/test/room/FakeMatrixRoom.kt | 5 ++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt index 4fae22ad57..70da8e7364 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt @@ -20,6 +20,7 @@ import androidx.compose.runtime.Immutable 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.UserId +import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableMap @@ -49,5 +50,6 @@ data class MatrixRoomInfo( val notificationCount: Long, val userDefinedNotificationMode: RoomNotificationMode?, val hasRoomCall: Boolean, - val activeRoomCallParticipants: ImmutableList + val activeRoomCallParticipants: ImmutableList, + val heroes: ImmutableList, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index d01a7d1740..45b2135f31 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -22,10 +22,12 @@ import io.element.android.libraries.matrix.api.core.UserId 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.RoomNotificationMode +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentMap +import org.matrix.rustcomponents.sdk.RoomHero import org.matrix.rustcomponents.sdk.Membership as RustMembership import org.matrix.rustcomponents.sdk.RoomInfo as RustRoomInfo import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode @@ -55,7 +57,8 @@ class MatrixRoomInfoMapper { notificationCount = it.notificationCount.toLong(), userDefinedNotificationMode = it.userDefinedNotificationMode?.map(), hasRoomCall = it.hasRoomCall, - activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList() + activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList(), + heroes = it.heroes.map { hero -> hero.map() }.toImmutableList() ) } } @@ -72,6 +75,15 @@ fun RustRoomNotificationMode.map(): RoomNotificationMode = when (this) { RustRoomNotificationMode.MUTE -> RoomNotificationMode.MUTE } +/** + * Map a RoomHero to a MatrixUser. There is not need to create a RoomHero type on the application side. + */ +fun RoomHero.map(): MatrixUser = MatrixUser( + userId = UserId(userId), + displayName = displayName, + avatarUrl = avatarUrl +) + fun mapPowerLevels(powerLevels: Map): ImmutableMap { return powerLevels.mapKeys { (key, _) -> UserId(key) }.toPersistentMap() } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 5583f6b11e..558d7abb60 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -45,6 +45,7 @@ import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerL import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings import io.element.android.libraries.matrix.test.AN_AVATAR_URL @@ -754,7 +755,8 @@ fun aRoomInfo( userDefinedNotificationMode: RoomNotificationMode? = null, hasRoomCall: Boolean = false, userPowerLevels: ImmutableMap = persistentMapOf(), - activeRoomCallParticipants: List = emptyList() + activeRoomCallParticipants: List = emptyList(), + heroes: List = emptyList(), ) = MatrixRoomInfo( id = id, name = name, @@ -779,6 +781,7 @@ fun aRoomInfo( hasRoomCall = hasRoomCall, userPowerLevels = userPowerLevels, activeRoomCallParticipants = activeRoomCallParticipants.toImmutableList(), + heroes = heroes.toImmutableList(), ) fun defaultRoomPowerLevels() = MatrixRoomPowerLevels( From f886bf7105102256fae643bfb1499a85fd3e9dc8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 11:22:14 +0200 Subject: [PATCH 02/19] Introduce CompositeAvatar to render heroes when main AvatarData does not have URL. --- .../designsystem/components/avatar/Avatar.kt | 21 ++- .../components/avatar/CompositeAvatar.kt | 153 ++++++++++++++++++ 2 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/CompositeAvatar.kt diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt index 173716aee3..4e8183977f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage @@ -52,18 +53,22 @@ fun Avatar( avatarData: AvatarData, modifier: Modifier = Modifier, contentDescription: String? = null, + // If not null, will be used instead of the size from avatarData + forcedAvatarSize: Dp? = null, ) { val commonModifier = modifier - .size(avatarData.size.dp) + .size(forcedAvatarSize ?: avatarData.size.dp) .clip(CircleShape) if (avatarData.url.isNullOrBlank()) { InitialsAvatar( avatarData = avatarData, + forcedAvatarSize = forcedAvatarSize, modifier = commonModifier, ) } else { ImageAvatar( avatarData = avatarData, + forcedAvatarSize = forcedAvatarSize, modifier = commonModifier, contentDescription = contentDescription, ) @@ -73,6 +78,7 @@ fun Avatar( @Composable private fun ImageAvatar( avatarData: AvatarData, + forcedAvatarSize: Dp?, modifier: Modifier = Modifier, contentDescription: String? = null, ) { @@ -98,9 +104,15 @@ private fun ImageAvatar( SideEffect { Timber.e(state.result.throwable, "Error loading avatar $state\n${state.result}") } - InitialsAvatar(avatarData = avatarData) + InitialsAvatar( + avatarData = avatarData, + forcedAvatarSize = forcedAvatarSize, + ) } - else -> InitialsAvatar(avatarData = avatarData) + else -> InitialsAvatar( + avatarData = avatarData, + forcedAvatarSize = forcedAvatarSize, + ) } } } @@ -109,13 +121,14 @@ private fun ImageAvatar( @Composable private fun InitialsAvatar( avatarData: AvatarData, + forcedAvatarSize: Dp?, modifier: Modifier = Modifier, ) { val avatarColors = AvatarColorsProvider.provide(avatarData.id, ElementTheme.isLightTheme) Box( modifier.background(color = avatarColors.background) ) { - val fontSize = avatarData.size.dp.toSp() / 2 + val fontSize = (forcedAvatarSize ?: avatarData.size.dp).toSp() / 2 val originalFont = ElementTheme.typography.fontHeadingMdBold val ratio = fontSize.value / originalFont.fontSize.value val lineHeight = originalFont.lineHeight * ratio 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 new file mode 100644 index 0000000000..df33f791a9 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/CompositeAvatar.kt @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.components.avatar + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.preview.ElementThemedPreview +import io.element.android.libraries.designsystem.preview.PreviewGroup +import java.util.Collections +import kotlin.math.PI +import kotlin.math.cos +import kotlin.math.sin + +@Composable +fun CompositeAvatar( + avatarData: AvatarData, + heroes: List, + modifier: Modifier = Modifier, + contentDescription: String? = null, +) { + if (avatarData.url != null || heroes.isEmpty()) { + Avatar(avatarData, modifier, contentDescription) + } else { + val limitedHeroes = heroes.take(4) + val numberOfHeroes = limitedHeroes.size + if (numberOfHeroes == 4) { + // Swap 2 and 3 so that the 4th hero is at the bottom right + Collections.swap(limitedHeroes, 2, 3) + } + when (numberOfHeroes) { + 0 -> { + // Cannot happen + } + 1 -> { + Avatar(heroes[0], modifier, contentDescription) + } + else -> { + val angle = 2 * Math.PI / numberOfHeroes + val offsetRadius = when (numberOfHeroes) { + 2 -> avatarData.size.dp.value / 4.2 + 3 -> avatarData.size.dp.value / 4.0 + 4 -> avatarData.size.dp.value / 3.1 + else -> error("Unsupported number of heroes: $numberOfHeroes") + } + val heroAvatarSize = when (numberOfHeroes) { + 2 -> avatarData.size.dp / 2.2f + 3 -> avatarData.size.dp / 2.4f + 4 -> avatarData.size.dp / 2.2f + else -> error("Unsupported number of heroes: $numberOfHeroes") + } + val angleOffset = when (numberOfHeroes) { + 2 -> PI + 3 -> 7 * PI / 6 + 4 -> 13 * PI / 4 + else -> error("Unsupported number of heroes: $numberOfHeroes") + } + Box( + modifier = modifier + .size(avatarData.size.dp) + .semantics { + this.contentDescription = contentDescription.orEmpty() + }, + contentAlignment = Alignment.Center, + ) { + limitedHeroes.forEachIndexed { index, heroAvatar -> + val xOffset = (offsetRadius * cos(angle * index.toDouble() + angleOffset)).dp + val yOffset = (offsetRadius * sin(angle * index.toDouble() + angleOffset)).dp + Box( + modifier = Modifier + .size(heroAvatarSize) + .offset( + x = xOffset, + y = yOffset, + ) + ) { + Avatar( + heroAvatar, + forcedAvatarSize = heroAvatarSize, + ) + } + } + } + } + } + } +} + +@Preview(group = PreviewGroup.Avatars) +@Composable +internal fun CompositeAvatarPreview() = ElementThemedPreview { + val mainAvatar = anAvatarData( + id = "Zac", + name = "Zac", + size = AvatarSize.RoomListItem, + ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + CompositeAvatar( + avatarData = mainAvatar, + heroes = List(0) { aHeroAvatarData(it) }, + ) + CompositeAvatar( + avatarData = mainAvatar, + heroes = List(1) { aHeroAvatarData(it) }, + ) + CompositeAvatar( + avatarData = mainAvatar, + heroes = List(2) { aHeroAvatarData(it) }, + ) + CompositeAvatar( + avatarData = mainAvatar, + heroes = List(3) { aHeroAvatarData(it) }, + ) + CompositeAvatar( + avatarData = mainAvatar, + heroes = List(4) { aHeroAvatarData(it) }, + ) + CompositeAvatar( + avatarData = mainAvatar, + heroes = List(5) { aHeroAvatarData(it) }, + ) + } +} + +private fun aHeroAvatarData(i: Int) = anAvatarData( + id = ('A' + i).toString(), + name = ('A' + i).toString() +) From ff63755165f0c84a988c3173b73d7ade78e51688 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 11:43:15 +0200 Subject: [PATCH 03/19] Add enum `EditProfileDetails` instead of reusing `RoomHeader` --- .../preferences/impl/user/editprofile/EditUserProfileView.kt | 2 +- .../libraries/designsystem/components/avatar/AvatarSize.kt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt index 167c301a35..d191ef2eee 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt @@ -109,7 +109,7 @@ fun EditUserProfileView( matrixId = state.userId.value, displayName = state.displayName, avatarUrl = state.userAvatarUrl, - avatarSize = AvatarSize.RoomHeader, + avatarSize = AvatarSize.EditProfileDetails, onAvatarClick = { onAvatarClick() }, modifier = Modifier.align(Alignment.CenterHorizontally), ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt index 54791f8505..c644f89772 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt @@ -55,4 +55,6 @@ enum class AvatarSize(val dp: Dp) { CustomRoomNotificationSetting(36.dp), RoomDirectoryItem(36.dp), + + EditProfileDetails(96.dp), } From 99c43a175d4d37cc47a09b0f3135e7a08ea5db85 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 11:59:38 +0200 Subject: [PATCH 04/19] Add heroes to `RoomSummaryDetails` --- .../android/libraries/matrix/api/roomlist/RoomSummary.kt | 2 ++ .../matrix/impl/roomlist/RoomSummaryDetailsFactory.kt | 1 + .../android/libraries/matrix/test/room/RoomSummaryFixture.kt | 3 +++ .../matrix/ui/components/RoomSummaryDetailsProvider.kt | 3 +++ 4 files changed, 9 insertions(+) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt index 425da8d3ca..1e38b00b61 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.message.RoomMessage +import io.element.android.libraries.matrix.api.user.MatrixUser sealed interface RoomSummary { data class Empty(val identifier: String) : RoomSummary @@ -52,6 +53,7 @@ data class RoomSummaryDetails( val isDm: Boolean, val isFavorite: Boolean, val currentUserMembership: CurrentUserMembership, + val heroes: List, ) { val lastMessageTimestamp = lastMessage?.originServerTs } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt index 3ccc071316..0ef31a6be2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt @@ -49,6 +49,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto isDm = roomInfo.isDirect && roomInfo.activeMembersCount.toLong() == 2L, isFavorite = roomInfo.isFavourite, currentUserMembership = roomInfo.membership.map(), + heroes = roomInfo.heroes.map { it.map() }, ) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index d9fdffa62a..611a68aad6 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.api.room.message.RoomMessage import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME @@ -78,6 +79,7 @@ fun aRoomSummaryDetails( isDm: Boolean = false, isFavorite: Boolean = false, currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED, + heroes: List = emptyList(), ) = RoomSummaryDetails( roomId = roomId, name = name, @@ -95,6 +97,7 @@ fun aRoomSummaryDetails( isDm = isDm, isFavorite = isFavorite, currentUserMembership = currentUserMembership, + heroes = heroes, ) fun aRoomMessage( diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt index a433f49395..275848f3fc 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt @@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.message.RoomMessage import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails +import io.element.android.libraries.matrix.api.user.MatrixUser open class RoomSummaryDetailsProvider : PreviewParameterProvider { override val values: Sequence @@ -50,6 +51,7 @@ fun aRoomSummaryDetails( isMarkedUnread: Boolean = false, isFavorite: Boolean = false, currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED, + heroes: List = emptyList(), ) = RoomSummaryDetails( roomId = roomId, name = name, @@ -67,4 +69,5 @@ fun aRoomSummaryDetails( isMarkedUnread = isMarkedUnread, isFavorite = isFavorite, currentUserMembership = currentUserMembership, + heroes = heroes, ) From 11e4ee34edccccebdf88eba1755111fc48a46066 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 13:10:25 +0200 Subject: [PATCH 05/19] 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 From 8aa7afd480f618238677c71bed30c123a9eba32b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 13:15:32 +0200 Subject: [PATCH 06/19] Add preview and fix rendering issue. --- .../features/roomdetails/impl/RoomDetailsStateProvider.kt | 2 ++ .../android/features/roomdetails/impl/RoomDetailsView.kt | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) 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 84b1514c4b..6c3e9bdac0 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 @@ -29,6 +29,7 @@ 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 io.element.android.libraries.matrix.ui.components.aMatrixUserList import kotlinx.collections.immutable.toPersistentList open class RoomDetailsStateProvider : PreviewParameterProvider { @@ -50,6 +51,7 @@ open class RoomDetailsStateProvider : PreviewParameterProvider ), aRoomDetailsState(canCall = false, canInvite = false), aRoomDetailsState(isPublic = false), + aRoomDetailsState(heroes = aMatrixUserList()), // Add other state here ) } 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 5fb78e1fe6..a243e34315 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 @@ -346,7 +346,6 @@ private fun RoomHeaderSection( ) }, modifier = Modifier - .size(70.dp) .clickable(enabled = avatarUrl != null) { openAvatarPreview(avatarUrl!!) } .testTag(TestTags.roomDetailAvatar) ) From 042ba6b35ef74c21bf503628004468602cafe157 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 14:14:05 +0200 Subject: [PATCH 07/19] Use heroes to render room avatars --- .../features/messages/impl/MessagesPresenter.kt | 16 ++++++++++++++++ .../features/messages/impl/MessagesState.kt | 2 ++ .../messages/impl/MessagesStateProvider.kt | 5 +++-- .../features/messages/impl/MessagesView.kt | 11 +++++++++-- .../roomlist/impl/components/RoomSummaryRow.kt | 7 +++++-- .../impl/model/RoomListRoomSummaryTest.kt | 3 +++ 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 065c81e407..3e70e9c026 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -92,6 +92,7 @@ import io.element.android.libraries.matrix.ui.room.canRedactOwnAsState import io.element.android.libraries.matrix.ui.room.canSendMessageAsState import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -151,6 +152,9 @@ class MessagesPresenter @AssistedInject constructor( val roomAvatar: AsyncData by remember { derivedStateOf { roomInfo?.avatarData()?.let { AsyncData.Success(it) } ?: AsyncData.Uninitialized } } + val heroes by remember { + derivedStateOf { roomInfo?.heroes().orEmpty().toPersistentList() } + } var hasDismissedInviteDialog by rememberSaveable { mutableStateOf(false) @@ -217,6 +221,7 @@ class MessagesPresenter @AssistedInject constructor( roomId = room.roomId, roomName = roomName, roomAvatar = roomAvatar, + heroes = heroes, userHasPermissionToSendMessage = userHasPermissionToSendMessage, userHasPermissionToRedactOwn = userHasPermissionToRedactOwn, userHasPermissionToRedactOther = userHasPermissionToRedactOther, @@ -250,6 +255,17 @@ class MessagesPresenter @AssistedInject constructor( ) } + private fun MatrixRoomInfo.heroes(): List { + return heroes.map { user -> + AvatarData( + id = user.userId.value, + name = user.displayName, + url = user.avatarUrl, + size = AvatarSize.TimelineRoom + ) + } + } + private fun CoroutineScope.handleTimelineAction( action: TimelineItemAction, targetEvent: TimelineItem.Event, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index 752aa94a9f..e8657d70bd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -29,12 +29,14 @@ import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.RoomId +import kotlinx.collections.immutable.ImmutableList @Immutable data class MessagesState( val roomId: RoomId, val roomName: AsyncData, val roomAvatar: AsyncData, + val heroes: ImmutableList, val userHasPermissionToSendMessage: Boolean, val userHasPermissionToRedactOwn: Boolean, val userHasPermissionToRedactOther: Boolean, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 526edfb1e7..1396d3e17c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -99,8 +99,8 @@ fun aMessagesState( userHasPermissionToSendReaction: Boolean = true, composerState: MessageComposerState = aMessageComposerState( textEditorState = TextEditorState.Rich(aRichTextEditorState(initialText = "Hello", initialFocus = true)), - isFullScreen = false, - mode = MessageComposerMode.Normal, + isFullScreen = false, + mode = MessageComposerMode.Normal, ), voiceMessageComposerState: VoiceMessageComposerState = aVoiceMessageComposerState(), timelineState: TimelineState = aTimelineState( @@ -121,6 +121,7 @@ fun aMessagesState( roomId = RoomId("!id:domain"), roomName = roomName, roomAvatar = roomAvatar, + heroes = persistentListOf(), userHasPermissionToSendMessage = userHasPermissionToSendMessage, userHasPermissionToRedactOwn = userHasPermissionToRedactOwn, userHasPermissionToRedactOther = userHasPermissionToRedactOther, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index b8997865ce..f28ff69905 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -83,9 +83,9 @@ import io.element.android.libraries.androidutils.ui.hideKeyboard import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialogType -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.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.preview.ElementPreview @@ -187,6 +187,7 @@ fun MessagesView( MessagesViewTopBar( roomName = state.roomName.dataOrNull(), roomAvatar = state.roomAvatar.dataOrNull(), + heroes = state.heroes, callState = state.callState, onBackClick = { // Since the textfield is now based on an Android view, this is no longer done automatically. @@ -442,6 +443,7 @@ private fun MessagesViewComposerBottomSheetContents( private fun MessagesViewTopBar( roomName: String?, roomAvatar: AvatarData?, + heroes: List, callState: RoomCallState, onRoomDetailsClick: () -> Unit, onJoinCallClick: () -> Unit, @@ -457,6 +459,7 @@ private fun MessagesViewTopBar( RoomAvatarAndNameRow( roomName = roomName, roomAvatar = roomAvatar, + heroes = heroes, modifier = titleModifier ) } else { @@ -500,13 +503,17 @@ private fun CallMenuItem( private fun RoomAvatarAndNameRow( roomName: String, roomAvatar: AvatarData, + heroes: List, modifier: Modifier = Modifier ) { Row( modifier = modifier, verticalAlignment = Alignment.CenterVertically ) { - Avatar(roomAvatar) + CompositeAvatar( + avatarData = roomAvatar, + heroes = heroes, + ) Spacer(modifier = Modifier.width(8.dp)) Text( text = roomName, diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt index d90faef985..f7602faa16 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt @@ -53,7 +53,7 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvid import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType import io.element.android.libraries.core.extensions.orEmpty import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom -import io.element.android.libraries.designsystem.components.avatar.Avatar +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.Button @@ -158,7 +158,10 @@ private fun RoomSummaryScaffoldRow( .padding(horizontal = 16.dp, vertical = 11.dp) .height(IntrinsicSize.Min), ) { - Avatar(room.avatarData) + CompositeAvatar( + avatarData = room.avatarData, + heroes = room.heroes, + ) Spacer(modifier = Modifier.width(16.dp)) Column( modifier = Modifier.fillMaxWidth(), diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryTest.kt index 6ad7c07960..bf24dfd6dd 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryTest.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME +import kotlinx.collections.immutable.toPersistentList import org.junit.Test class RoomListRoomSummaryTest { @@ -91,6 +92,7 @@ internal fun createRoomListRoomSummary( userDefinedNotificationMode: RoomNotificationMode? = null, isFavorite: Boolean = false, displayType: RoomSummaryDisplayType = RoomSummaryDisplayType.ROOM, + heroes: List = emptyList(), ) = RoomListRoomSummary( id = A_ROOM_ID.value, roomId = A_ROOM_ID, @@ -110,4 +112,5 @@ internal fun createRoomListRoomSummary( canonicalAlias = null, inviteSender = null, isDm = false, + heroes = heroes.toPersistentList(), ) From 99becc0ae6e03f9c7a48565708c05319bfd8fcba Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 14:35:12 +0200 Subject: [PATCH 08/19] Use heroes only for DMs. #1538 --- .../matrix/impl/room/MatrixRoomInfoMapper.kt | 2 +- .../libraries/matrix/impl/room/RoomInfoExt.kt | 33 +++++++++++++++++++ .../roomlist/RoomSummaryDetailsFactory.kt | 3 +- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index 45b2135f31..6a87b02a2b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -58,7 +58,7 @@ class MatrixRoomInfoMapper { userDefinedNotificationMode = it.userDefinedNotificationMode?.map(), hasRoomCall = it.hasRoomCall, activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList(), - heroes = it.heroes.map { hero -> hero.map() }.toImmutableList() + heroes = it.elementHeroes().toImmutableList() ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt new file mode 100644 index 0000000000..bd6cc7eda4 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.room + +import io.element.android.libraries.matrix.api.user.MatrixUser +import org.matrix.rustcomponents.sdk.RoomInfo + +/** + * Extract the heroes from the room info. + * For now we only use heroes for direct rooms with 2 members. + * Also we keep the heroes only if there is one single hero. + */ +fun RoomInfo.elementHeroes(): List { + return heroes + .takeIf { isDirect && activeMembersCount.toLong() == 2L } + ?.takeIf { it.size == 1 } + ?.map { it.map() } + .orEmpty() +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt index 0ef31a6be2..f45c843694 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt @@ -20,6 +20,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.roomlist.RoomSummaryDetails import io.element.android.libraries.matrix.impl.notificationsettings.RoomNotificationSettingsMapper +import io.element.android.libraries.matrix.impl.room.elementHeroes import io.element.android.libraries.matrix.impl.room.map import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.room.message.RoomMessageFactory @@ -49,7 +50,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto isDm = roomInfo.isDirect && roomInfo.activeMembersCount.toLong() == 2L, isFavorite = roomInfo.isFavourite, currentUserMembership = roomInfo.membership.map(), - heroes = roomInfo.heroes.map { it.map() }, + heroes = roomInfo.elementHeroes(), ) } } From 85538c90e6825400a1cde9e6da289c63e376876f Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 20 Jun 2024 12:55:37 +0000 Subject: [PATCH 09/19] Update screenshots --- ...sDark_null_RoomDetailsDark--1_3_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...sDark_null_RoomDetailsDark--1_3_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...Dark_null_RoomDetailsDark--1_3_null_10,NEXUS_5,1.0,en].png | 4 ++-- ...Dark_null_RoomDetailsDark--1_3_null_11,NEXUS_5,1.0,en].png | 4 ++-- ...Dark_null_RoomDetailsDark--1_3_null_12,NEXUS_5,1.0,en].png | 3 +++ ...sDark_null_RoomDetailsDark--1_3_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...sDark_null_RoomDetailsDark--1_3_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...sDark_null_RoomDetailsDark--1_3_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...sDark_null_RoomDetailsDark--1_3_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...sDark_null_RoomDetailsDark--1_3_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...sDark_null_RoomDetailsDark--1_3_null_9,NEXUS_5,1.0,en].png | 4 ++-- ...omDetails_null_RoomDetails--0_2_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...omDetails_null_RoomDetails--0_2_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...mDetails_null_RoomDetails--0_2_null_10,NEXUS_5,1.0,en].png | 4 ++-- ...mDetails_null_RoomDetails--0_2_null_11,NEXUS_5,1.0,en].png | 4 ++-- ...mDetails_null_RoomDetails--0_2_null_12,NEXUS_5,1.0,en].png | 3 +++ ...omDetails_null_RoomDetails--0_2_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...omDetails_null_RoomDetails--0_2_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...omDetails_null_RoomDetails--0_2_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...omDetails_null_RoomDetails--0_2_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...omDetails_null_RoomDetails--0_2_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...omDetails_null_RoomDetails--0_2_null_9,NEXUS_5,1.0,en].png | 4 ++-- ...r_Avatar_null_Avatars_Avatar_0_null_66,NEXUS_5,1.0,en].png | 3 +++ ...r_Avatar_null_Avatars_Avatar_0_null_67,NEXUS_5,1.0,en].png | 3 +++ ...r_Avatar_null_Avatars_Avatar_0_null_68,NEXUS_5,1.0,en].png | 3 +++ ...ar_null_Avatars_CompositeAvatar_0_null,NEXUS_5,1.0,en].png | 3 +++ 26 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_12,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_12,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_66,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_67,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_68,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_CompositeAvatar_null_Avatars_CompositeAvatar_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_0,NEXUS_5,1.0,en].png index d2f9ab5db9..8a8a532ba2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4744d8211b2afaa0e45d018e618296be417db72976a7fe248044e69dc419747 -size 46405 +oid sha256:b66bfca625a2c5abbb99eb63840c99d941331f74da6741203f382ee49fec29fa +size 45772 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_1,NEXUS_5,1.0,en].png index 1866e67ab6..773c3fe950 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b070a8b1d40d9b944a35f1ca9d034dac4d8f75fcd2ce29ca90a6c0d02eefe567 -size 34637 +oid sha256:5e1320dbc665a15434e9ea46bc8f085cb0a1dfe1a328d41139401ebd8ef23f84 +size 34975 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_10,NEXUS_5,1.0,en].png index 1273e8ea35..99307b9b97 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_10,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_10,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6975f45047b144416e394c61d50b2c67296e075ab87521b2bd19190e688b2db -size 44684 +oid sha256:24d1b09fbf025b954711e4bd8392d32675568154bbd06ce8c69f4a8deb91a958 +size 43695 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_11,NEXUS_5,1.0,en].png index 4bfc4b76c6..f11e3460cb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_11,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_11,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06ecef645a1770f028a0be5b519d9fa058896599764b679d431302530dfe5bfd -size 43593 +oid sha256:05d47c7317111c9e7ac34f66705a8344114501c35d05d630f2146e128300077d +size 42587 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_12,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..2218fcc35e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_12,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5491a9525166428c8b1ce94aaf3ef56aa5415cab19f8bcd99be128c265925e9 +size 45669 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_2,NEXUS_5,1.0,en].png index 2eabc0dccf..028a806260 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d89dc9226478c87a95f381474dc952372506c59f5797b1ebc06a73f79cda7d4 -size 36723 +oid sha256:42590cba46dc5f9e0d4e9504d1ea854c5f5f3fdf3acaddca2604988164153beb +size 37065 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_3,NEXUS_5,1.0,en].png index 91047eaa4c..5e5446c198 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fee91322d75a86cf574c0bae99fc7534a7a41f0aa9925554c2cecdd1f67616a2 -size 35594 +oid sha256:30e9d873c187481341222a986741061eb84162127d7e0d086d3c957d9ef2d2d8 +size 35945 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_4,NEXUS_5,1.0,en].png index 91424489cd..d9e920eb75 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb91e113a89b29e43529fee0140b04c9d45aa6dee95b636e8b02cb697f8eaec3 -size 42854 +oid sha256:189e30f39a33924a6da727d4caa4ce117df66cc9dd1857c4909649cf8db51fdb +size 43191 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_7,NEXUS_5,1.0,en].png index 6c046aa84e..e70f6778f8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dcb14bafbaeb398a7351528b9756888190cb3614b64ced30604525d33042d0b7 -size 45983 +oid sha256:a0f12af0b98d2d145d5443554a0657cd0699fe27f86447873630a189cbce615a +size 45008 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_8,NEXUS_5,1.0,en].png index 8273c91f0a..f4023197f4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27f9fd42938231cbedef25c60c0bf5c38445ed4ae3c43076a3d0d1de781c1571 -size 44882 +oid sha256:db2babbe88dd81723ecf8f1c83fa73042efb590d04f1b12aaabf102f7f576dd9 +size 43883 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_9,NEXUS_5,1.0,en].png index 162cd9c264..866944d635 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetailsDark_null_RoomDetailsDark--1_3_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d851ccac1aea76e629d3b8ef381595e734e8d02789ebea3a28b5f40dfb07040f -size 44838 +oid sha256:53056291448931a702d761557712626259f04a3969f128553a7bc7a172d74d5b +size 43840 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_0,NEXUS_5,1.0,en].png index 2ef84f644e..0c89045531 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a077772fbbcd2e5096e9fa5907705e5bb3d04692c597510f825102ce31afb6a -size 47451 +oid sha256:d69018133b9a3ebf36e7819031df2c8b8bc19f1e7632cfeabc02ca6bcf76ffce +size 46744 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_1,NEXUS_5,1.0,en].png index 2467e58bcd..0e629da29e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e60750a386993ee7e14a2f1e9afcbfb898d6212f9f043d67431017991b53a3c4 -size 35470 +oid sha256:374166110a04cee8f63d1d330601976970e5abcd92947cfb284e61613cf47f51 +size 35727 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_10,NEXUS_5,1.0,en].png index bc1dc06a99..0d9c8a73b7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_10,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_10,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d805eed0dbdf07599c836af16e904ec5a6ebe4adb0b9ebfa5200f2065630cfa -size 45596 +oid sha256:04a0838ac192efeacb821d23ed8b3ce8305b8e8084beb0e5a0fbc56cfa1ce964 +size 44435 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_11,NEXUS_5,1.0,en].png index 1635ac1d06..343de082ef 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_11,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_11,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c04bd5c13058d696364295110fc4b323b424766bda0ba42c13b2ed772e8f6520 -size 44474 +oid sha256:6d760e5015257bd8d608749c1926c6177e4d0ef70d5d5f32764e970f4c80cb43 +size 43331 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_12,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..3ba823f05b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_12,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63d2319dc4617d805f0b652983e4bb7b6e4aa7c2e9c6ec37398fce2e2413a79d +size 46441 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_2,NEXUS_5,1.0,en].png index 7cc2a1b656..e8e3831962 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb96628c10622b9f39b9723b4c3a7b1a7e38a643753a42159af63e8f00a2f51c -size 37610 +oid sha256:8c3dec8246e5605c61a9132cea048c5afaad35751246ffd81160c33782c26c93 +size 37861 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_3,NEXUS_5,1.0,en].png index 7a1641860a..3f3136ce6c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f84aea29dfb13dbe42c6e466b3afd7258742bf2c0411039ab93e554803945333 -size 36229 +oid sha256:c8491d21c160851bbe3a0362edae05e46cf9cb072ca4bf41ad569a3a6c57097c +size 36458 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_4,NEXUS_5,1.0,en].png index f09ef9182f..00cc501d4b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e7e580cd945db94a37cfaa162ab709ade3a830f20a42bb98a28fd7650114a90 -size 43740 +oid sha256:f7f08cac8eecb3ae6067f756411d0ec5607d3207832cfe69858ef1189f18ee45 +size 43996 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_7,NEXUS_5,1.0,en].png index b3e71b54a2..7a9d976302 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14b22efc30f883ca6812f9e87bf8eaecc3d37479fa5421026fcaf7b01a11e952 -size 46986 +oid sha256:ea0cfd0f222862a8becdd4b4a7f2e47a4a7d83ecb1ff761889c46631d7d43e97 +size 45861 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_8,NEXUS_5,1.0,en].png index 0af429e838..9a0cf77937 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45a3856e5d802c02302318caf584b4356122c3412bea177944ec8edab0c809c0 -size 45846 +oid sha256:cd7aa71f1d24d4cacafb4aaea8802d1493e317604d5ea35f0d9fac1a304d7f19 +size 44718 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_9,NEXUS_5,1.0,en].png index 1dc805428d..a2ec270d02 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_RoomDetails_null_RoomDetails--0_2_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd29438c4d913cd920e2f19e85f9098d6a486a401fcd8e14a9f7a323dd5c334c -size 45773 +oid sha256:234e65b2caa1f23f9e4d0e01c142d22df0d407851e554a7db3e0b09c57acf47a +size 44626 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_66,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_66,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..3697470264 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_66,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6be06e6a243feb8096a2f121e5cadbd5d82351807b537c938e0e7cbfdf52739 +size 21115 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_67,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_67,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..7ad7b48d2a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_67,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94607803d470f7f5772cbf421b3e56a845556773b3545cae5b42314a1804a02a +size 18858 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_68,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_68,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..fc23c2c5ad --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_68,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f3a7f0a4944f35fd726d5090eab08140b57332e6f7d8eb475fc6bf9ef37bcdf +size 26033 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_CompositeAvatar_null_Avatars_CompositeAvatar_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_CompositeAvatar_null_Avatars_CompositeAvatar_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..c48605599a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_CompositeAvatar_null_Avatars_CompositeAvatar_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa80768048c3247ede26c831a9d16a2f9c27774b5d9b75e70cb31e0f26b4d411 +size 27620 From 0b9f5a5214187d4752f494c63b6c0d64f0b04543 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 15:00:09 +0200 Subject: [PATCH 10/19] Add enum `Suggestion` instead of reusing `TimelineRoom` --- .../impl/mentions/MentionSuggestionsPickerView.kt | 12 ++++++------ .../designsystem/components/avatar/AvatarSize.kt | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsPickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsPickerView.kt index 9af2407657..48c626680e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsPickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mentions/MentionSuggestionsPickerView.kt @@ -93,14 +93,14 @@ private fun RoomMemberSuggestionItemView( modifier: Modifier = Modifier, ) { Row(modifier = modifier.clickable { onSelectSuggestion(memberSuggestion) }, horizontalArrangement = Arrangement.spacedBy(16.dp)) { - val avatarSize = AvatarSize.TimelineRoom val avatarData = when (memberSuggestion) { - is ResolvedMentionSuggestion.AtRoom -> roomAvatar?.copy(size = avatarSize) ?: AvatarData(roomId, roomName, null, avatarSize) + is ResolvedMentionSuggestion.AtRoom -> roomAvatar?.copy(size = AvatarSize.Suggestion) + ?: AvatarData(roomId, roomName, null, AvatarSize.Suggestion) is ResolvedMentionSuggestion.Member -> AvatarData( - memberSuggestion.roomMember.userId.value, - memberSuggestion.roomMember.displayName, - memberSuggestion.roomMember.avatarUrl, - avatarSize, + id = memberSuggestion.roomMember.userId.value, + name = memberSuggestion.roomMember.displayName, + url = memberSuggestion.roomMember.avatarUrl, + size = AvatarSize.Suggestion, ) } val title = when (memberSuggestion) { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt index c644f89772..e56c580abb 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt @@ -57,4 +57,6 @@ enum class AvatarSize(val dp: Dp) { RoomDirectoryItem(36.dp), EditProfileDetails(96.dp), + + Suggestion(32.dp), } From 4a991276d3a010f89412b19b3b4077738b88ffa5 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 20 Jun 2024 13:15:59 +0000 Subject: [PATCH 11/19] Update screenshots --- ...ar_Avatar_null_Avatars_Avatar_0_null_69,NEXUS_5,1.0,en].png | 3 +++ ...ar_Avatar_null_Avatars_Avatar_0_null_70,NEXUS_5,1.0,en].png | 3 +++ ...ar_Avatar_null_Avatars_Avatar_0_null_71,NEXUS_5,1.0,en].png | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_69,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_70,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_71,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_69,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_69,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..2202019ea4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_69,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61d634e424c3858902d03a50a128ecbba4c62766ebba97cd04f6eb147f41f71d +size 15042 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_70,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_70,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..594f49999b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_70,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fea2725865c6277387d8f9d4f1bc980548b671f2946c89dbb9f4cad34be80d7 +size 14267 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_71,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_71,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..b294ff8e75 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_Avatar_null_Avatars_Avatar_0_null_71,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e88e6991bca9f0c99c28b6126b10135d0ba8de1faa7bc6174e6f66bc11b2ce03 +size 16794 From 2ee3763890f793ac4dfceae717fe15ded781d062 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 15:38:43 +0200 Subject: [PATCH 12/19] Fix test. --- .../android/features/roomdetails/impl/RoomDetailsViewTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt index 62dbac449c..dc1c1735cb 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt @@ -126,6 +126,7 @@ class RoomDetailsViewTest { } } + @Config(qualifiers = "h1024dp") @Test fun `click on add topic emit expected event`() { ensureCalledOnceWithParam(RoomDetailsAction.AddTopic) { callback -> From 84f42537b83ca927eb62f9f5c0a4b91a53fd7420 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 15:53:42 +0200 Subject: [PATCH 13/19] Use ImmutableList in Composable. --- .../features/messages/impl/MessagesView.kt | 4 ++-- .../features/roomdetails/impl/RoomDetailsView.kt | 7 ++++--- .../components/avatar/CompositeAvatar.kt | 16 +++++++++------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index f28ff69905..2da1d64642 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -443,7 +443,7 @@ private fun MessagesViewComposerBottomSheetContents( private fun MessagesViewTopBar( roomName: String?, roomAvatar: AvatarData?, - heroes: List, + heroes: ImmutableList, callState: RoomCallState, onRoomDetailsClick: () -> Unit, onJoinCallClick: () -> Unit, @@ -503,7 +503,7 @@ private fun CallMenuItem( private fun RoomAvatarAndNameRow( roomName: String, roomAvatar: AvatarData, - heroes: List, + heroes: ImmutableList, modifier: Modifier = Modifier ) { Row( 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 a243e34315..1269ff1f4d 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 @@ -26,7 +26,6 @@ import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons @@ -85,6 +84,8 @@ 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 +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toPersistentList @Composable fun RoomDetailsView( @@ -326,7 +327,7 @@ private fun RoomHeaderSection( roomAlias: RoomAlias?, isEncrypted: Boolean, isPublic: Boolean, - heroes: List = emptyList(), + heroes: ImmutableList, openAvatarPreview: (url: String) -> Unit, ) { Column( @@ -344,7 +345,7 @@ private fun RoomHeaderSection( url = user.avatarUrl, size = AvatarSize.RoomHeader ) - }, + }.toPersistentList(), modifier = Modifier .clickable(enabled = avatarUrl != null) { openAvatarPreview(avatarUrl!!) } .testTag(TestTags.roomDetailAvatar) 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 ada1671eea..2422f32c92 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 @@ -30,6 +30,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toPersistentList import java.util.Collections import kotlin.math.PI import kotlin.math.cos @@ -38,7 +40,7 @@ import kotlin.math.sin @Composable fun CompositeAvatar( avatarData: AvatarData, - heroes: List, + heroes: ImmutableList, modifier: Modifier = Modifier, contentDescription: String? = null, ) { @@ -122,27 +124,27 @@ internal fun CompositeAvatarPreview() = ElementThemedPreview { ) { CompositeAvatar( avatarData = mainAvatar, - heroes = List(0) { aHeroAvatarData(it) }, + heroes = List(0) { aHeroAvatarData(it) }.toPersistentList(), ) CompositeAvatar( avatarData = mainAvatar, - heroes = List(1) { aHeroAvatarData(it) }, + heroes = List(1) { aHeroAvatarData(it) }.toPersistentList(), ) CompositeAvatar( avatarData = mainAvatar, - heroes = List(2) { aHeroAvatarData(it) }, + heroes = List(2) { aHeroAvatarData(it) }.toPersistentList(), ) CompositeAvatar( avatarData = mainAvatar, - heroes = List(3) { aHeroAvatarData(it) }, + heroes = List(3) { aHeroAvatarData(it) }.toPersistentList(), ) CompositeAvatar( avatarData = mainAvatar, - heroes = List(4) { aHeroAvatarData(it) }, + heroes = List(4) { aHeroAvatarData(it) }.toPersistentList(), ) CompositeAvatar( avatarData = mainAvatar, - heroes = List(5) { aHeroAvatarData(it) }, + heroes = List(5) { aHeroAvatarData(it) }.toPersistentList(), ) } } From 9f7f0b9acb0a9ef3d07b110bbe4f0bc63edbd64f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 16:04:12 +0200 Subject: [PATCH 14/19] Use extension MatrixUser.getAvatarData and fix compilation issue. --- .../features/messages/impl/MessagesPresenter.kt | 8 ++------ .../edit/EditDefaultNotificationSettingView.kt | 11 ++++------- .../features/roomdetails/impl/RoomDetailsView.kt | 8 ++------ .../impl/datasource/RoomListRoomSummaryFactory.kt | 10 +++------- .../libraries/matrix/ui/components/SelectedRoom.kt | 13 +++++-------- .../libraries/roomselect/impl/RoomSelectView.kt | 13 +++++-------- 6 files changed, 21 insertions(+), 42 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 3e70e9c026..cc3d571735 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -86,6 +86,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.room.canCall import io.element.android.libraries.matrix.ui.room.canRedactOtherAsState import io.element.android.libraries.matrix.ui.room.canRedactOwnAsState @@ -257,12 +258,7 @@ class MessagesPresenter @AssistedInject constructor( private fun MatrixRoomInfo.heroes(): List { return heroes.map { user -> - AvatarData( - id = user.userId.value, - name = user.displayName, - url = user.avatarUrl, - size = AvatarSize.TimelineRoom - ) + user.getAvatarData(size = AvatarSize.TimelineRoom) } } 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 aac1ae94a8..3222add2fe 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 @@ -37,7 +37,9 @@ import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.Text 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.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.toPersistentList /** * A view that allows a user to edit the default notification setting for rooms. This can be set separately @@ -117,13 +119,8 @@ fun EditDefaultNotificationSettingView( CompositeAvatar( avatarData = avatarData, heroes = summary.details.heroes.map { user -> - AvatarData( - id = user.userId.value, - name = user.displayName, - url = user.avatarUrl, - size = AvatarSize.CustomRoomNotificationSetting, - ) - } + user.getAvatarData(size = AvatarSize.CustomRoomNotificationSetting) + }.toPersistentList() ) }, onClick = { 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 1269ff1f4d..56838c534a 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 @@ -81,6 +81,7 @@ 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.matrix.ui.model.getAvatarData import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -339,12 +340,7 @@ private fun RoomHeaderSection( 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 - ) + user.getAvatarData(size = AvatarSize.RoomHeader) }.toPersistentList(), modifier = Modifier .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 058573caf5..82e9c1d503 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 @@ -26,6 +26,7 @@ import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter 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.getAvatarData import io.element.android.libraries.matrix.ui.model.toInviteSender import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -94,13 +95,8 @@ class RoomListRoomSummaryFactory @Inject constructor( } else { RoomSummaryDisplayType.ROOM }, - heroes = roomSummary.details.heroes.map { - AvatarData( - id = it.userId.value, - name = it.displayName, - url = it.avatarUrl, - size = AvatarSize.RoomListItem, - ) + heroes = roomSummary.details.heroes.map { user -> + user.getAvatarData(size = AvatarSize.RoomListItem) }.toImmutableList(), ) } 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 a88ad47388..96711e159f 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 @@ -45,7 +45,9 @@ import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.toImmutableList @Composable fun SelectedRoom( @@ -67,14 +69,9 @@ fun SelectedRoom( roomSummary.avatarUrl, AvatarSize.SelectedRoom, ), - heroes = roomSummary.heroes.map { - AvatarData( - id = it.userId.value, - name = it.displayName, - url = it.avatarUrl, - size = AvatarSize.SelectedRoom - ) - } + heroes = roomSummary.heroes.map { user -> + user.getAvatarData(size = AvatarSize.SelectedRoom) + }.toImmutableList() ) Text( // If name is null, we do not have space to render "No room name", so just use `#` here. 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 fce89c5c7e..0dc86525f7 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 @@ -59,9 +59,11 @@ import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails import io.element.android.libraries.matrix.ui.components.SelectedRoom +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.roomselect.api.RoomSelectMode import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toPersistentList @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -228,14 +230,9 @@ private fun RoomSummaryView( url = summary.avatarUrl, size = AvatarSize.RoomSelectRoomListItem, ), - heroes = summary.heroes.map { - AvatarData( - it.userId.value, - it.displayName, - it.avatarUrl, - AvatarSize.RoomSelectRoomListItem, - ) - } + heroes = summary.heroes.map { user -> + user.getAvatarData(size = AvatarSize.RoomSelectRoomListItem) + }.toPersistentList() ) Column( modifier = Modifier From 7cdcf872b354bf76521c7be28ba88686ee05833c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 16:16:55 +0200 Subject: [PATCH 15/19] Create extension `RoomSummaryDetails.getAvatarData` to avoid code duplication. --- .../EditDefaultNotificationSettingView.kt | 9 +----- .../datasource/RoomListRoomSummaryFactory.kt | 7 +---- .../matrix/ui/components/SelectedRoom.kt | 8 +----- .../matrix/ui/model/RoomSummaryExtension.kt | 28 +++++++++++++++++++ .../roomselect/impl/RoomSelectView.kt | 8 +----- 5 files changed, 32 insertions(+), 28 deletions(-) create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomSummaryExtension.kt 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 3222add2fe..c69970bd3f 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,7 +25,6 @@ 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.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 @@ -98,12 +97,6 @@ fun EditDefaultNotificationSettingView( RoomNotificationMode.MUTE -> stringResource(id = CommonStrings.common_mute) null -> "" } - val avatarData = AvatarData( - id = summary.identifier(), - name = summary.details.name, - url = summary.details.avatarUrl, - size = AvatarSize.CustomRoomNotificationSetting, - ) ListItem( headlineContent = { val roomName = summary.details.name @@ -117,7 +110,7 @@ fun EditDefaultNotificationSettingView( }, leadingContent = ListItemContent.Custom { CompositeAvatar( - avatarData = avatarData, + avatarData = summary.details.getAvatarData(size = AvatarSize.CustomRoomNotificationSetting), heroes = summary.details.heroes.map { user -> user.getAvatarData(size = AvatarSize.CustomRoomNotificationSetting) }.toPersistentList() 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 82e9c1d503..9e1f50b69c 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 @@ -64,12 +64,7 @@ class RoomListRoomSummaryFactory @Inject constructor( fun create(roomSummary: RoomSummary.Filled): RoomListRoomSummary { val roomIdentifier = roomSummary.identifier() - val avatarData = AvatarData( - id = roomIdentifier, - name = roomSummary.details.name, - url = roomSummary.details.avatarUrl, - size = AvatarSize.RoomListItem, - ) + val avatarData = roomSummary.details.getAvatarData(size = AvatarSize.RoomListItem) return RoomListRoomSummary( id = roomIdentifier, roomId = RoomId(roomIdentifier), 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 96711e159f..f34b071379 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,7 +36,6 @@ 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.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 @@ -63,12 +62,7 @@ fun SelectedRoom( horizontalAlignment = Alignment.CenterHorizontally, ) { CompositeAvatar( - avatarData = AvatarData( - roomSummary.roomId.value, - roomSummary.name, - roomSummary.avatarUrl, - AvatarSize.SelectedRoom, - ), + avatarData = roomSummary.getAvatarData(size = AvatarSize.SelectedRoom), heroes = roomSummary.heroes.map { user -> user.getAvatarData(size = AvatarSize.SelectedRoom) }.toImmutableList() diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomSummaryExtension.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomSummaryExtension.kt new file mode 100644 index 0000000000..dd86d375f3 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomSummaryExtension.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.ui.model + +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails + +fun RoomSummaryDetails.getAvatarData(size: AvatarSize) = AvatarData( + id = roomId.value, + name = name, + url = avatarUrl, + size = size, +) 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 0dc86525f7..7ade4f759d 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,7 +41,6 @@ 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.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 @@ -224,12 +223,7 @@ private fun RoomSummaryView( verticalAlignment = Alignment.CenterVertically ) { CompositeAvatar( - avatarData = AvatarData( - id = summary.roomId.value, - name = summary.name, - url = summary.avatarUrl, - size = AvatarSize.RoomSelectRoomListItem, - ), + avatarData = summary.getAvatarData(size = AvatarSize.RoomSelectRoomListItem), heroes = summary.heroes.map { user -> user.getAvatarData(size = AvatarSize.RoomSelectRoomListItem) }.toPersistentList() From b122c2c0a0a80dbac9ee9cfa7d4cd129583893cc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 16:21:30 +0200 Subject: [PATCH 16/19] Code simplification. --- .../datasource/RoomListRoomSummaryFactory.kt | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) 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 9e1f50b69c..18ba73bdc1 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 @@ -26,6 +26,7 @@ import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter 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.api.roomlist.RoomSummaryDetails import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.toInviteSender import kotlinx.collections.immutable.persistentListOf @@ -63,34 +64,37 @@ class RoomListRoomSummaryFactory @Inject constructor( } fun create(roomSummary: RoomSummary.Filled): RoomListRoomSummary { - val roomIdentifier = roomSummary.identifier() - val avatarData = roomSummary.details.getAvatarData(size = AvatarSize.RoomListItem) + return create(roomSummary.details) + } + + private fun create(details: RoomSummaryDetails): RoomListRoomSummary { + val avatarData = details.getAvatarData(size = AvatarSize.RoomListItem) return RoomListRoomSummary( - id = roomIdentifier, - roomId = RoomId(roomIdentifier), - name = roomSummary.details.name, - numberOfUnreadMessages = roomSummary.details.numUnreadMessages, - numberOfUnreadMentions = roomSummary.details.numUnreadMentions, - numberOfUnreadNotifications = roomSummary.details.numUnreadNotifications, - isMarkedUnread = roomSummary.details.isMarkedUnread, - timestamp = lastMessageTimestampFormatter.format(roomSummary.details.lastMessageTimestamp), - lastMessage = roomSummary.details.lastMessage?.let { message -> - roomLastMessageFormatter.format(message.event, roomSummary.details.isDirect) + id = details.roomId.value, + roomId = details.roomId, + name = details.name, + numberOfUnreadMessages = details.numUnreadMessages, + numberOfUnreadMentions = details.numUnreadMentions, + numberOfUnreadNotifications = details.numUnreadNotifications, + isMarkedUnread = details.isMarkedUnread, + timestamp = lastMessageTimestampFormatter.format(details.lastMessageTimestamp), + lastMessage = details.lastMessage?.let { message -> + roomLastMessageFormatter.format(message.event, details.isDirect) }.orEmpty(), avatarData = avatarData, - userDefinedNotificationMode = roomSummary.details.userDefinedNotificationMode, - hasRoomCall = roomSummary.details.hasRoomCall, - isDirect = roomSummary.details.isDirect, - isFavorite = roomSummary.details.isFavorite, - inviteSender = roomSummary.details.inviter?.toInviteSender(), - isDm = roomSummary.details.isDm, - canonicalAlias = roomSummary.details.canonicalAlias, - displayType = if (roomSummary.details.currentUserMembership == CurrentUserMembership.INVITED) { + userDefinedNotificationMode = details.userDefinedNotificationMode, + hasRoomCall = details.hasRoomCall, + isDirect = details.isDirect, + isFavorite = details.isFavorite, + inviteSender = details.inviter?.toInviteSender(), + isDm = details.isDm, + canonicalAlias = details.canonicalAlias, + displayType = if (details.currentUserMembership == CurrentUserMembership.INVITED) { RoomSummaryDisplayType.INVITE } else { RoomSummaryDisplayType.ROOM }, - heroes = roomSummary.details.heroes.map { user -> + heroes = details.heroes.map { user -> user.getAvatarData(size = AvatarSize.RoomListItem) }.toImmutableList(), ) From 62d05f290746831362020c0f8ca0e5b34d3e71a9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 17:47:13 +0200 Subject: [PATCH 17/19] Use extension --- .../roomdetails/impl/members/RoomMemberListView.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt index 488286ce00..b12ecf4ec8 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt @@ -67,7 +67,7 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.api.room.toMatrixUser import io.element.android.libraries.matrix.ui.components.MatrixUserRow import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList @@ -276,11 +276,7 @@ private fun RoomMemberListItem( } MatrixUserRow( modifier = modifier.clickable(onClick = onClick), - matrixUser = MatrixUser( - userId = roomMember.userId, - displayName = roomMember.displayName, - avatarUrl = roomMember.avatarUrl, - ), + matrixUser = roomMember.toMatrixUser(), avatarSize = AvatarSize.UserListItem, trailingContent = roleText?.let { @Composable { From 5f32643af43d274731ba1cff7e4c08a42800b6fe Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 17:51:35 +0200 Subject: [PATCH 18/19] Create extension `RoomMember.getAvatarData` to avoid code duplication. --- .../moderation/RoomMembersModerationView.kt | 9 ++---- .../changeroles/ChangeRolesView.kt | 3 +- .../libraries/matrix/ui/model/InviteSender.kt | 7 +---- .../matrix/ui/model/RoomMemberExtension.kt | 28 +++++++++++++++++++ 4 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomMemberExtension.kt diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationView.kt index 03c602fdd4..a96e4ef46f 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/moderation/RoomMembersModerationView.kt @@ -45,7 +45,6 @@ import io.element.android.libraries.designsystem.components.async.AsyncIndicator import io.element.android.libraries.designsystem.components.async.AsyncIndicatorHost import io.element.android.libraries.designsystem.components.async.rememberAsyncIndicatorState 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.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.list.ListItemContent @@ -59,6 +58,7 @@ import io.element.android.libraries.designsystem.theme.components.Text 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.getBestName +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.launch @@ -217,12 +217,7 @@ private fun RoomMemberActionsBottomSheet( modifier = Modifier.padding(vertical = 16.dp) ) { Avatar( - avatarData = AvatarData( - id = roomMember.userId.value, - name = roomMember.displayName, - url = roomMember.avatarUrl, - size = AvatarSize.RoomListManageUser, - ), + avatarData = roomMember.getAvatarData(size = AvatarSize.RoomListManageUser), modifier = Modifier .padding(bottom = 28.dp) .align(Alignment.CenterHorizontally) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesView.kt index f5b1873717..d89ad29b78 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesView.kt @@ -81,6 +81,7 @@ import io.element.android.libraries.matrix.api.room.getBestName import io.element.android.libraries.matrix.api.room.toMatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.SelectedUsersRowList +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList @@ -327,7 +328,7 @@ private fun ListMemberItem( } MemberRow( modifier = Modifier.clickable(enabled = canToggle, onClick = { onToggleSelection(roomMember) }), - avatarData = AvatarData(roomMember.userId.value, roomMember.displayName, roomMember.avatarUrl, AvatarSize.UserListItem), + avatarData = roomMember.getAvatarData(size = AvatarSize.UserListItem), name = roomMember.getBestName(), userId = roomMember.userId.value.takeIf { roomMember.displayName?.isNotBlank() == true }, isPending = roomMember.membership == RoomMembershipState.INVITE, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/InviteSender.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/InviteSender.kt index 410fb7edbd..dcc8e6e327 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/InviteSender.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/InviteSender.kt @@ -60,10 +60,5 @@ data class InviteSender( fun RoomMember.toInviteSender() = InviteSender( userId = userId, displayName = displayName ?: "", - avatarData = AvatarData( - id = userId.value, - name = displayName, - url = avatarUrl, - size = AvatarSize.InviteSender, - ), + avatarData = getAvatarData(size = AvatarSize.InviteSender), ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomMemberExtension.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomMemberExtension.kt new file mode 100644 index 0000000000..95ec1cc230 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomMemberExtension.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.ui.model + +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.matrix.api.room.RoomMember + +fun RoomMember.getAvatarData(size: AvatarSize) = AvatarData( + id = userId.value, + name = displayName, + url = avatarUrl, + size = size, +) From 5ea495da1b4381084273c04c7ecc4193eb0f0052 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Jun 2024 17:59:26 +0200 Subject: [PATCH 19/19] Use `repeat` in the Preview. --- .../components/avatar/CompositeAvatar.kt | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) 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 2422f32c92..6ae505e048 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 @@ -122,30 +122,12 @@ internal fun CompositeAvatarPreview() = ElementThemedPreview { Row( horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - CompositeAvatar( - avatarData = mainAvatar, - heroes = List(0) { aHeroAvatarData(it) }.toPersistentList(), - ) - CompositeAvatar( - avatarData = mainAvatar, - heroes = List(1) { aHeroAvatarData(it) }.toPersistentList(), - ) - CompositeAvatar( - avatarData = mainAvatar, - heroes = List(2) { aHeroAvatarData(it) }.toPersistentList(), - ) - CompositeAvatar( - avatarData = mainAvatar, - heroes = List(3) { aHeroAvatarData(it) }.toPersistentList(), - ) - CompositeAvatar( - avatarData = mainAvatar, - heroes = List(4) { aHeroAvatarData(it) }.toPersistentList(), - ) - CompositeAvatar( - avatarData = mainAvatar, - heroes = List(5) { aHeroAvatarData(it) }.toPersistentList(), - ) + repeat(6) { nbOfHeroes -> + CompositeAvatar( + avatarData = mainAvatar, + heroes = List(nbOfHeroes) { aHeroAvatarData(it) }.toPersistentList(), + ) + } } }