Use DmAvatars in header of DM details.
This commit is contained in:
@@ -45,6 +45,7 @@ import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.canSendState
|
||||
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
|
||||
import io.element.android.libraries.matrix.ui.room.canCall
|
||||
import io.element.android.libraries.matrix.ui.room.getCurrentRoomMember
|
||||
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
|
||||
@@ -98,8 +99,9 @@ class RoomDetailsPresenter @Inject constructor(
|
||||
val canEditTopic by getCanSendState(membersState, StateEventType.ROOM_TOPIC)
|
||||
val canJoinCall by room.canCall(updateKey = syncUpdateTimestamp)
|
||||
val dmMember by room.getDirectRoomMember(membersState)
|
||||
val currentMember by room.getCurrentRoomMember(membersState)
|
||||
val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember)
|
||||
val roomType by getRoomType(dmMember)
|
||||
val roomType by getRoomType(dmMember, currentMember)
|
||||
|
||||
val topicState = remember(canEditTopic, roomTopic, roomType) {
|
||||
val topic = roomTopic
|
||||
@@ -165,10 +167,16 @@ class RoomDetailsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getRoomType(dmMember: RoomMember?): State<RoomDetailsType> = remember(dmMember) {
|
||||
private fun getRoomType(
|
||||
dmMember: RoomMember?,
|
||||
currentMember: RoomMember?,
|
||||
): State<RoomDetailsType> = remember(dmMember, currentMember) {
|
||||
derivedStateOf {
|
||||
if (dmMember != null) {
|
||||
RoomDetailsType.Dm(dmMember)
|
||||
if (dmMember != null && currentMember != null) {
|
||||
RoomDetailsType.Dm(
|
||||
me = currentMember,
|
||||
roomMember = dmMember,
|
||||
)
|
||||
} else {
|
||||
RoomDetailsType.Room
|
||||
}
|
||||
|
||||
@@ -52,7 +52,10 @@ data class RoomDetailsState(
|
||||
@Immutable
|
||||
sealed interface RoomDetailsType {
|
||||
data object Room : RoomDetailsType
|
||||
data class Dm(val roomMember: RoomMember) : RoomDetailsType
|
||||
data class Dm(
|
||||
val me: RoomMember,
|
||||
val roomMember: RoomMember,
|
||||
) : RoomDetailsType
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
||||
@@ -19,6 +19,7 @@ package io.element.android.features.roomdetails.impl
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||
import io.element.android.features.leaveroom.api.aLeaveRoomState
|
||||
import io.element.android.features.roomdetails.impl.members.aRoomMember
|
||||
import io.element.android.features.userprofile.shared.UserProfileState
|
||||
import io.element.android.features.userprofile.shared.aUserProfileState
|
||||
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||
@@ -141,6 +142,9 @@ fun aDmRoomDetailsState(
|
||||
roomName: String = "Daniel",
|
||||
) = aRoomDetailsState(
|
||||
roomName = roomName,
|
||||
roomType = RoomDetailsType.Dm(aDmRoomMember(isIgnored = isDmMemberIgnored)),
|
||||
roomType = RoomDetailsType.Dm(
|
||||
aRoomMember(),
|
||||
aDmRoomMember(isIgnored = isDmMemberIgnored),
|
||||
),
|
||||
roomMemberDetailsState = aUserProfileState()
|
||||
)
|
||||
|
||||
@@ -40,6 +40,7 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
@@ -48,7 +49,6 @@ import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomView
|
||||
import io.element.android.features.roomdetails.impl.components.RoomBadge
|
||||
import io.element.android.features.userprofile.shared.UserProfileHeaderSection
|
||||
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
|
||||
@@ -56,6 +56,7 @@ import io.element.android.libraries.designsystem.components.ClickableLinkText
|
||||
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.avatar.DmAvatars
|
||||
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
|
||||
@@ -78,6 +79,7 @@ import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
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.RoomNotificationMode
|
||||
import io.element.android.libraries.matrix.api.room.getBestName
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
@@ -137,13 +139,12 @@ fun RoomDetailsView(
|
||||
)
|
||||
}
|
||||
is RoomDetailsType.Dm -> {
|
||||
val member = state.roomType.roomMember
|
||||
UserProfileHeaderSection(
|
||||
avatarUrl = state.roomAvatarUrl ?: member.avatarUrl,
|
||||
userId = member.userId,
|
||||
userName = state.roomName,
|
||||
openAvatarPreview = { avatarUrl ->
|
||||
openAvatarPreview(member.getBestName(), avatarUrl)
|
||||
DmHeaderSection(
|
||||
me = state.roomType.me,
|
||||
otherMember = state.roomType.roomMember,
|
||||
roomName = state.roomName,
|
||||
openAvatarPreview = { name, avatarUrl ->
|
||||
openAvatarPreview(name, avatarUrl)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -359,6 +360,47 @@ private fun RoomHeaderSection(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DmHeaderSection(
|
||||
me: RoomMember,
|
||||
otherMember: RoomMember,
|
||||
roomName: String,
|
||||
openAvatarPreview: (name: String, url: String) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
DmAvatars(
|
||||
userAvatarData = me.getAvatarData(size = AvatarSize.DmCluster),
|
||||
otherUserAvatarData = otherMember.getAvatarData(size = AvatarSize.DmCluster),
|
||||
openAvatarPreview = { url -> openAvatarPreview(me.getBestName(), url) },
|
||||
openOtherAvatarPreview = { url -> openAvatarPreview(roomName, url) },
|
||||
)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Text(
|
||||
modifier = Modifier.clipToBounds(),
|
||||
text = roomName,
|
||||
style = ElementTheme.typography.fontHeadingLgBold,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
Text(
|
||||
text = otherMember.userId.value,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Spacer(Modifier.height(40.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BadgeList(
|
||||
isEncrypted: Boolean,
|
||||
|
||||
@@ -169,8 +169,12 @@ class RoomDetailsPresenterTest {
|
||||
val presenter = createRoomDetailsPresenter(room)
|
||||
presenter.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.roomType).isEqualTo(RoomDetailsType.Dm(otherRoomMember))
|
||||
|
||||
assertThat(initialState.roomType).isEqualTo(
|
||||
RoomDetailsType.Dm(
|
||||
me = myRoomMember,
|
||||
roomMember = otherRoomMember,
|
||||
)
|
||||
)
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.element.android.features.roomdetails.impl.members.aRoomMember
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
@@ -177,7 +178,11 @@ class RoomDetailsViewTest {
|
||||
fun `click on avatar test on DM`() {
|
||||
val eventsRecorder = EventsRecorder<RoomDetailsEvent>(expectEvents = false)
|
||||
val state = aRoomDetailsState(
|
||||
roomType = RoomDetailsType.Dm(aDmRoomMember(avatarUrl = "an_avatar_url")),
|
||||
roomType = RoomDetailsType.Dm(
|
||||
aRoomMember(),
|
||||
aDmRoomMember(avatarUrl = "an_avatar_url"),
|
||||
),
|
||||
roomName = "Daniel",
|
||||
eventSink = eventsRecorder,
|
||||
)
|
||||
val callback = EnsureCalledOnceWithTwoParams("Daniel", "an_avatar_url")
|
||||
|
||||
@@ -34,6 +34,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.text.toPx
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
|
||||
/**
|
||||
* https://www.figma.com/design/A2pAEvTEpJZBiOPUlcMnKi/Settings-%2B-Room-Details-(new)?node-id=1787-56333
|
||||
@@ -90,6 +92,7 @@ fun DmAvatars(
|
||||
.clickable(enabled = otherUserAvatarData.url != null) {
|
||||
otherUserAvatarData.url?.let { openOtherAvatarPreview(it) }
|
||||
}
|
||||
.testTag(TestTags.memberDetailAvatar)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,3 +63,14 @@ fun MatrixRoom.getDirectRoomMember(roomMembersState: MatrixRoomMembersState): St
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MatrixRoom.getCurrentRoomMember(roomMembersState: MatrixRoomMembersState): State<RoomMember?> {
|
||||
val roomMembers = roomMembersState.roomMembers()
|
||||
return remember(roomMembersState) {
|
||||
derivedStateOf {
|
||||
roomMembers
|
||||
?.find { it.userId == sessionId }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user