Use just the other user's avatar for DM details (#6738)
* Use just the other user's avatar for DM details. Remove `DmAvatars` component and other no longer needed data. * Improve selection indicator by clipping the avatar to a circle shape * Update screenshots --------- Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
parent
245c30c18a
commit
4a4b3e07ef
56 changed files with 128 additions and 286 deletions
|
|
@ -47,7 +47,6 @@ import io.element.android.libraries.matrix.api.room.join.JoinRule
|
|||
import io.element.android.libraries.matrix.api.room.powerlevels.canEditRolesAndPermissions
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState
|
||||
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
|
||||
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.roomMemberIdentityStateChange
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
|
|
@ -99,9 +98,8 @@ class RoomDetailsPresenter(
|
|||
val canonicalAlias by remember { derivedStateOf { roomInfo.canonicalAlias } }
|
||||
val isEncrypted by remember { derivedStateOf { roomInfo.isEncrypted == true } }
|
||||
val dmMember by room.getDirectRoomMember(membersState)
|
||||
val currentMember by room.getCurrentRoomMember(membersState)
|
||||
val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember)
|
||||
val roomType = getRoomType(dmMember, currentMember)
|
||||
val roomType = getRoomType(dmMember)
|
||||
val roomCallState = roomCallStatePresenter.present()
|
||||
val joinedMemberCount by remember { derivedStateOf { roomInfo.joinedMembersCount } }
|
||||
|
||||
|
|
@ -210,15 +208,9 @@ class RoomDetailsPresenter(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun getRoomType(
|
||||
dmMember: RoomMember?,
|
||||
currentMember: RoomMember?,
|
||||
): RoomDetailsType = remember(dmMember, currentMember) {
|
||||
if (dmMember != null && currentMember != null) {
|
||||
RoomDetailsType.Dm(
|
||||
me = currentMember,
|
||||
otherMember = dmMember,
|
||||
)
|
||||
private fun getRoomType(dmMember: RoomMember?): RoomDetailsType = remember(dmMember) {
|
||||
if (dmMember != null) {
|
||||
RoomDetailsType.Dm(otherMember = dmMember)
|
||||
} else {
|
||||
RoomDetailsType.Room
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,10 +77,7 @@ data class RoomDetailsState(
|
|||
@Immutable
|
||||
sealed interface RoomDetailsType {
|
||||
data object Room : RoomDetailsType
|
||||
data class Dm(
|
||||
val me: RoomMember,
|
||||
val otherMember: RoomMember,
|
||||
) : RoomDetailsType
|
||||
data class Dm(val otherMember: RoomMember) : RoomDetailsType
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent
|
|||
import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||
import io.element.android.features.roomcall.api.RoomCallState
|
||||
import io.element.android.features.roomcall.api.aStandByCallState
|
||||
import io.element.android.features.roomdetails.impl.members.aRoomMember
|
||||
import io.element.android.features.userprofile.api.UserProfileState
|
||||
import io.element.android.features.userprofile.api.UserProfileVerificationState
|
||||
import io.element.android.features.userprofile.shared.aUserProfileState
|
||||
|
|
@ -179,10 +178,7 @@ fun aDmRoomDetailsState(
|
|||
roomName = roomName,
|
||||
isPublic = false,
|
||||
isEncrypted = isEncrypted,
|
||||
roomType = RoomDetailsType.Dm(
|
||||
me = aRoomMember(),
|
||||
otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored),
|
||||
),
|
||||
roomType = RoomDetailsType.Dm(otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored)),
|
||||
roomMemberDetailsState = aUserProfileState(
|
||||
isBlocked = AsyncData.Success(isDmMemberIgnored),
|
||||
verificationState = dmRoomMemberVerificationState,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ 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.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
|
@ -31,6 +32,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.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
|
|
@ -52,7 +54,6 @@ 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.AvatarType
|
||||
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
|
||||
|
|
@ -91,6 +92,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
|||
import io.element.android.services.analytics.compose.LocalAnalyticsService
|
||||
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
@Composable
|
||||
|
|
@ -154,9 +156,9 @@ fun RoomDetailsView(
|
|||
}
|
||||
is RoomDetailsType.Dm -> {
|
||||
DmHeaderSection(
|
||||
me = state.roomType.me,
|
||||
otherMember = state.roomType.otherMember,
|
||||
roomName = state.roomName,
|
||||
isTombstoned = state.isTombstoned,
|
||||
openAvatarPreview = { name, avatarUrl ->
|
||||
openAvatarPreview(name, avatarUrl)
|
||||
},
|
||||
|
|
@ -417,6 +419,7 @@ private fun RoomHeaderSection(
|
|||
),
|
||||
contentDescription = stringResource(CommonStrings.a11y_room_avatar),
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.clickable(
|
||||
enabled = avatarUrl != null,
|
||||
onClickLabel = stringResource(CommonStrings.action_view),
|
||||
|
|
@ -435,9 +438,9 @@ private fun RoomHeaderSection(
|
|||
|
||||
@Composable
|
||||
private fun DmHeaderSection(
|
||||
me: RoomMember,
|
||||
otherMember: RoomMember,
|
||||
roomName: String,
|
||||
isTombstoned: Boolean,
|
||||
openAvatarPreview: (name: String, url: String) -> Unit,
|
||||
onSubtitleClick: (String) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
|
|
@ -448,11 +451,24 @@ private fun DmHeaderSection(
|
|||
.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) },
|
||||
Avatar(
|
||||
avatarData = AvatarData(otherMember.userId.value, roomName, otherMember.avatarUrl, AvatarSize.RoomDetailsHeader),
|
||||
avatarType = AvatarType.Room(
|
||||
heroes = persistentListOf(
|
||||
otherMember.getAvatarData(size = AvatarSize.RoomDetailsHeader)
|
||||
),
|
||||
isTombstoned = isTombstoned,
|
||||
),
|
||||
contentDescription = stringResource(CommonStrings.a11y_room_avatar),
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.clickable(
|
||||
enabled = otherMember.avatarUrl != null,
|
||||
onClickLabel = stringResource(CommonStrings.action_view),
|
||||
) {
|
||||
openAvatarPreview(otherMember.getBestName(), otherMember.avatarUrl!!)
|
||||
}
|
||||
.testTag(TestTags.roomDetailAvatar)
|
||||
)
|
||||
TitleAndSubtitle(
|
||||
title = roomName,
|
||||
|
|
|
|||
|
|
@ -206,12 +206,7 @@ class RoomDetailsPresenterTest {
|
|||
val presenter = createRoomDetailsPresenter(room)
|
||||
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.roomType).isEqualTo(
|
||||
RoomDetailsType.Dm(
|
||||
me = myRoomMember,
|
||||
otherMember = otherRoomMember,
|
||||
)
|
||||
)
|
||||
assertThat(initialState.roomType).isEqualTo(RoomDetailsType.Dm(otherMember = otherRoomMember))
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,10 +126,7 @@ class RoomDetailsViewTest {
|
|||
state = aRoomDetailsState(
|
||||
eventSink = EventsRecorder(expectEvents = false),
|
||||
canInvite = true,
|
||||
roomType = RoomDetailsType.Dm(
|
||||
aRoomMember(UserId("@me:local.org")),
|
||||
aRoomMember(UserId("@other:local.org"))
|
||||
),
|
||||
roomType = RoomDetailsType.Dm(aRoomMember(UserId("@other:local.org"))),
|
||||
),
|
||||
onJoinCallClick = callback,
|
||||
)
|
||||
|
|
@ -232,10 +229,7 @@ class RoomDetailsViewTest {
|
|||
fun `click on avatar test on DM`() = runAndroidComposeUiTest {
|
||||
val eventsRecorder = EventsRecorder<RoomDetailsEvent>(expectEvents = false)
|
||||
val state = aRoomDetailsState(
|
||||
roomType = RoomDetailsType.Dm(
|
||||
aRoomMember(),
|
||||
aDmRoomMember(avatarUrl = "an_avatar_url"),
|
||||
),
|
||||
roomType = RoomDetailsType.Dm(aDmRoomMember(avatarUrl = "an_avatar_url"),),
|
||||
roomName = "Daniel",
|
||||
eventSink = eventsRecorder,
|
||||
)
|
||||
|
|
@ -244,7 +238,7 @@ class RoomDetailsViewTest {
|
|||
state = state,
|
||||
openAvatarPreview = callback,
|
||||
)
|
||||
onNodeWithTag(TestTags.memberDetailAvatar.value).performClick()
|
||||
onNodeWithTag(TestTags.roomDetailAvatar.value).performClick()
|
||||
callback.assertSuccess()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue