Romo details: reorder items

Fixes #6824
This commit is contained in:
Benoit Marty
2026-06-01 17:34:36 +02:00
parent abb1b2ad50
commit 6222416b17
6 changed files with 85 additions and 83 deletions
@@ -174,7 +174,7 @@ class RoomDetailsPresenter(
} }
} }
val roomMemberDetailsState = roomMemberDetailsPresenter?.present() val dmOtherMemberDetailsState = roomMemberDetailsPresenter?.present()
val hasMemberVerificationViolations by produceState(false) { val hasMemberVerificationViolations by produceState(false) {
room.roomMemberIdentityStateChange(waitForEncryption = true) room.roomMemberIdentityStateChange(waitForEncryption = true)
@@ -196,7 +196,7 @@ class RoomDetailsPresenter(
canEdit = roomType == RoomDetailsType.Room && permissions.editDetailsPermissions.hasAny, canEdit = roomType == RoomDetailsType.Room && permissions.editDetailsPermissions.hasAny,
roomCallState = roomCallState, roomCallState = roomCallState,
roomType = roomType, roomType = roomType,
roomMemberDetailsState = roomMemberDetailsState, dmOtherMemberDetailsState = dmOtherMemberDetailsState,
leaveRoomState = leaveRoomState, leaveRoomState = leaveRoomState,
roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(),
isFavorite = isFavorite, isFavorite = isFavorite,
@@ -31,7 +31,7 @@ data class RoomDetailsState(
val memberCount: Long, val memberCount: Long,
val isEncrypted: Boolean, val isEncrypted: Boolean,
val roomType: RoomDetailsType, val roomType: RoomDetailsType,
val roomMemberDetailsState: UserProfileState?, val dmOtherMemberDetailsState: UserProfileState?,
val canEdit: Boolean, val canEdit: Boolean,
val canInvite: Boolean, val canInvite: Boolean,
val roomCallState: RoomCallState, val roomCallState: RoomCallState,
@@ -106,7 +106,7 @@ fun aRoomDetailsState(
canEdit: Boolean = false, canEdit: Boolean = false,
roomCallState: RoomCallState = aStandByCallState(), roomCallState: RoomCallState = aStandByCallState(),
roomType: RoomDetailsType = RoomDetailsType.Room, roomType: RoomDetailsType = RoomDetailsType.Room,
roomMemberDetailsState: UserProfileState? = null, dmOtherMemberDetailsState: UserProfileState? = null,
leaveRoomState: LeaveRoomState = aLeaveRoomState(), leaveRoomState: LeaveRoomState = aLeaveRoomState(),
roomNotificationSettings: RoomNotificationSettings = aRoomNotificationSettings(), roomNotificationSettings: RoomNotificationSettings = aRoomNotificationSettings(),
isFavorite: Boolean = false, isFavorite: Boolean = false,
@@ -137,7 +137,7 @@ fun aRoomDetailsState(
canEdit = canEdit, canEdit = canEdit,
roomCallState = roomCallState, roomCallState = roomCallState,
roomType = roomType, roomType = roomType,
roomMemberDetailsState = roomMemberDetailsState, dmOtherMemberDetailsState = dmOtherMemberDetailsState,
leaveRoomState = leaveRoomState, leaveRoomState = leaveRoomState,
roomNotificationSettings = roomNotificationSettings, roomNotificationSettings = roomNotificationSettings,
isFavorite = isFavorite, isFavorite = isFavorite,
@@ -184,7 +184,7 @@ fun aDmRoomDetailsState(
isEncrypted = isEncrypted, isEncrypted = isEncrypted,
canInvite = true, canInvite = true,
roomType = RoomDetailsType.Dm(otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored)), roomType = RoomDetailsType.Dm(otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored)),
roomMemberDetailsState = aUserProfileState( dmOtherMemberDetailsState = aUserProfileState(
isBlocked = AsyncData.Success(isDmMemberIgnored), isBlocked = AsyncData.Success(isDmMemberIgnored),
verificationState = dmRoomMemberVerificationState, verificationState = dmRoomMemberVerificationState,
) )
@@ -43,6 +43,7 @@ import im.vector.app.features.analytics.plan.Interaction
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.roomcall.api.hasPermissionToJoin import io.element.android.features.roomcall.api.hasPermissionToJoin
import io.element.android.features.userprofile.api.UserProfileState
import io.element.android.features.userprofile.api.UserProfileVerificationState import io.element.android.features.userprofile.api.UserProfileVerificationState
import io.element.android.features.userprofile.shared.blockuser.BlockUserDialogs import io.element.android.features.userprofile.shared.blockuser.BlockUserDialogs
import io.element.android.features.userprofile.shared.blockuser.BlockUserSection import io.element.android.features.userprofile.shared.blockuser.BlockUserSection
@@ -64,7 +65,7 @@ import io.element.android.libraries.designsystem.modifiers.niceClickable
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight import io.element.android.libraries.designsystem.preview.PreviewWithExtraLargeHeight
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
@@ -229,66 +230,11 @@ fun RoomDetailsView(
) )
} }
} }
// Room content
PreferenceCategory { PreferenceCategory {
if (state.roomNotificationSettings != null) { MediaGalleryItem(
NotificationItem( onClick = openMediaGallery
isDefaultMode = state.roomNotificationSettings.isDefault,
openRoomNotificationSettings = openRoomNotificationSettings
)
}
FavoriteItem(
isFavorite = state.isFavorite,
onFavoriteChanges = {
state.eventSink(RoomDetailsEvent.SetFavorite(it))
}
) )
if (state.canShowSecurityAndPrivacy) {
SecurityAndPrivacyItem(
onClick = onSecurityAndPrivacyClick
)
}
}
state.roomMemberDetailsState?.let { dmMemberDetails ->
if (state.canInvite) {
PreferenceCategory {
InviteItem(onClick = invitePeople)
}
}
PreferenceCategory {
ProfileItem(
verificationState = dmMemberDetails.verificationState,
onClick = { onProfileClick(dmMemberDetails.userId) }
)
}
}
if (state.roomType is RoomDetailsType.Room) {
PreferenceCategory {
MembersItem(
memberCount = state.memberCount,
hasVerificationViolations = state.hasMemberVerificationViolations,
openRoomMemberList = openRoomMemberList,
)
if (state.canShowKnockRequests) {
KnockRequestsItem(
knockRequestsCount = state.knockRequestsCount,
onKnockRequestsClick = onKnockRequestsClick
)
}
if (state.displayRolesAndPermissionsSettings) {
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_details_roles_and_permissions)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Admin())),
onClick = openAdminSettings,
)
}
}
}
PreferenceCategory {
PinnedMessagesItem( PinnedMessagesItem(
pinnedMessagesCount = state.pinnedMessagesCount, pinnedMessagesCount = state.pinnedMessagesCount,
onPinnedMessagesClick = onPinnedMessagesClick onPinnedMessagesClick = onPinnedMessagesClick
@@ -296,23 +242,72 @@ fun RoomDetailsView(
PollsItem( PollsItem(
openPollHistory = openPollHistory openPollHistory = openPollHistory
) )
MediaGalleryItem( }
onClick = openMediaGallery when (state.roomType) {
is RoomDetailsType.Room -> {
PreferenceCategory {
MembersItem(
memberCount = state.memberCount,
hasVerificationViolations = state.hasMemberVerificationViolations,
openRoomMemberList = openRoomMemberList,
)
if (state.canShowKnockRequests) {
KnockRequestsItem(
knockRequestsCount = state.knockRequestsCount,
onKnockRequestsClick = onKnockRequestsClick
)
}
if (state.displayRolesAndPermissionsSettings) {
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_details_roles_and_permissions)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Admin())),
onClick = openAdminSettings,
)
}
}
}
is RoomDetailsType.Dm -> {
if (state.canInvite) {
// Note: for rooms the invite action is a Main action
PreferenceCategory {
InviteItem(onClick = invitePeople)
}
}
state.dmOtherMemberDetailsState?.let { dmMemberDetails ->
PreferenceCategory {
ProfileItem(
verificationState = dmMemberDetails.verificationState,
onClick = { onProfileClick(dmMemberDetails.userId) }
)
}
}
}
}
PreferenceCategory {
if (state.roomNotificationSettings != null) {
NotificationItem(
isDefaultMode = state.roomNotificationSettings.isDefault,
openRoomNotificationSettings = openRoomNotificationSettings
)
}
FavoriteItem(
isFavorite = state.isFavorite,
onFavoriteChanges = {
state.eventSink(RoomDetailsEvent.SetFavorite(it))
}
) )
if (state.canShowSecurityAndPrivacy && state.roomType is RoomDetailsType.Room) {
SecurityAndPrivacyItem(
onClick = onSecurityAndPrivacyClick
)
}
} }
if (state.roomType is RoomDetailsType.Dm && state.roomMemberDetailsState != null) {
val roomMemberState = state.roomMemberDetailsState
BlockUserSection(roomMemberState)
BlockUserDialogs(roomMemberState)
}
OtherActionsSection( OtherActionsSection(
dmOtherMemberDetailsState = state.dmOtherMemberDetailsState,
canReportRoom = state.canReportRoom, canReportRoom = state.canReportRoom,
onReportRoomClick = onReportRoomClick, onReportRoomClick = onReportRoomClick,
onLeaveRoomClick = { state.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true)) } onLeaveRoomClick = { state.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true)) }
) )
if (state.showDebugInfo) { if (state.showDebugInfo) {
DebugInfoSection( DebugInfoSection(
roomId = state.roomId, roomId = state.roomId,
@@ -803,9 +798,13 @@ private fun OtherActionsSection(
canReportRoom: Boolean, canReportRoom: Boolean,
onReportRoomClick: () -> Unit, onReportRoomClick: () -> Unit,
onLeaveRoomClick: () -> Unit, onLeaveRoomClick: () -> Unit,
dmOtherMemberDetailsState: UserProfileState?,
) { ) {
PreferenceCategory(showTopDivider = true) { PreferenceCategory {
if (canReportRoom) { if (dmOtherMemberDetailsState != null) {
BlockUserSection(dmOtherMemberDetailsState)
BlockUserDialogs(dmOtherMemberDetailsState)
} else if (canReportRoom) {
ListItem( ListItem(
headlineContent = { headlineContent = {
Text(stringResource(CommonStrings.action_report_room)) Text(stringResource(CommonStrings.action_report_room))
@@ -832,7 +831,7 @@ private fun DebugInfoSection(
roomVersion: String?, roomVersion: String?,
) { ) {
val context = LocalContext.current val context = LocalContext.current
PreferenceCategory(showTopDivider = true) { PreferenceCategory {
val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard)
ListItem( ListItem(
headlineContent = { headlineContent = {
@@ -870,17 +869,17 @@ private fun DebugInfoSection(
} }
} }
@PreviewWithLargeHeight @PreviewWithExtraLargeHeight
@Composable @Composable
internal fun RoomDetailsPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) = internal fun RoomDetailsPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
ElementPreviewLight { ContentToPreview(state) } ElementPreviewLight { ContentToPreview(state) }
@PreviewWithLargeHeight @PreviewWithExtraLargeHeight
@Composable @Composable
internal fun RoomDetailsDarkPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) = internal fun RoomDetailsDarkPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
ElementPreviewDark { ContentToPreview(state) } ElementPreviewDark { ContentToPreview(state) }
@PreviewWithLargeHeight @PreviewWithExtraLargeHeight
@Composable @Composable
internal fun RoomDetailsA11yPreview() = ElementPreview { internal fun RoomDetailsA11yPreview() = ElementPreview {
ContentToPreview( ContentToPreview(
@@ -334,7 +334,7 @@ class RoomDetailsViewTest {
setRoomDetailView( setRoomDetailView(
state = aRoomDetailsState( state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false), eventSink = EventsRecorder(expectEvents = false),
roomMemberDetailsState = aUserProfileState(userId = A_USER_ID), dmOtherMemberDetailsState = aUserProfileState(userId = A_USER_ID),
), ),
onProfileClick = callback, onProfileClick = callback,
) )
@@ -352,7 +352,7 @@ class RoomDetailsViewTest {
roomType = RoomDetailsType.Dm( roomType = RoomDetailsType.Dm(
aDmRoomMember(userId = UserId("@other:local.org")), aDmRoomMember(userId = UserId("@other:local.org")),
), ),
roomMemberDetailsState = aUserProfileState(userId = A_USER_ID), dmOtherMemberDetailsState = aUserProfileState(userId = A_USER_ID),
canInvite = true, canInvite = true,
), ),
invitePeople = callback, invitePeople = callback,
@@ -16,3 +16,6 @@ import androidx.compose.ui.tooling.preview.Preview
*/ */
@Preview(heightDp = 1000) @Preview(heightDp = 1000)
annotation class PreviewWithLargeHeight annotation class PreviewWithLargeHeight
@Preview(heightDp = 1600)
annotation class PreviewWithExtraLargeHeight