From 7050076bebac46df01fcf15a8199cda306feb5c1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Sep 2025 16:52:56 +0200 Subject: [PATCH] feature (space) : add trailing action to SpaceRoomItemView --- .../features/space/impl/SpaceStateProvider.kt | 49 +++++++++------- libraries/matrixui/build.gradle.kts | 1 + .../matrix/ui/components/SpaceRoomItemView.kt | 39 ++++++++++--- .../matrix/ui/components/SpaceRoomProvider.kt | 56 +++++++++++++++++++ 4 files changed, 116 insertions(+), 29 deletions(-) create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomProvider.kt diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt index cf2fcf92b5..07ebaa0a90 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceStateProvider.kt @@ -9,6 +9,7 @@ package io.element.android.features.space.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider 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.spaces.SpaceRoom import io.element.android.libraries.previewutils.room.aSpaceRoom import kotlinx.collections.immutable.toImmutableList @@ -17,24 +18,22 @@ import kotlinx.collections.immutable.toImmutableSet open class SpaceStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - aSpaceState(), aSpaceState( - parentSpace = aSpaceRoom( - name = null, - numJoinedMembers = 5, - childrenCount = 10, - worldReadable = true, - ), - hasMoreToLoad = true, + + ), aSpaceState( + parentSpace = aSpaceRoom( + name = null, + numJoinedMembers = 5, + childrenCount = 10, + worldReadable = true, ), - aSpaceState( - hasMoreToLoad = true, - children = aListOfSpaceRooms(), - ), - aSpaceState( - hasMoreToLoad = false, - children = aListOfSpaceRooms() - ) + hasMoreToLoad = true, + ), aSpaceState( + hasMoreToLoad = true, + children = aListOfSpaceRooms(), + ), aSpaceState( + hasMoreToLoad = false, children = aListOfSpaceRooms() + ) // Add other states here ) } @@ -56,13 +55,21 @@ fun aSpaceState( seenSpaceInvites = seenSpaceInvites.toImmutableSet(), hideInvitesAvatar = hideInvitesAvatar, hasMoreToLoad = hasMoreToLoad, - eventSink = {} -) + eventSink = {}) private fun aListOfSpaceRooms(): List { return listOf( - aSpaceRoom(roomId = RoomId("!spaceId0:example.com")), - aSpaceRoom(roomId = RoomId("!spaceId1:example.com")), - aSpaceRoom(roomId = RoomId("!spaceId2:example.com")), + aSpaceRoom( + roomId = RoomId("!spaceId0:example.com"), + state = null, + ), + aSpaceRoom( + roomId = RoomId("!spaceId1:example.com"), + state = CurrentUserMembership.JOINED, + ), + aSpaceRoom( + roomId = RoomId("!spaceId2:example.com"), + state = CurrentUserMembership.INVITED, + ), ) } diff --git a/libraries/matrixui/build.gradle.kts b/libraries/matrixui/build.gradle.kts index a500186587..96045f3a93 100644 --- a/libraries/matrixui/build.gradle.kts +++ b/libraries/matrixui/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { implementation(libs.coil.gif) implementation(libs.coil.network.okhttp) implementation(libs.jsoup) + implementation(projects.libraries.previewutils) testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt index e599b75cab..c98c830c20 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomItemView.kt @@ -20,8 +20,10 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.ripple import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -31,6 +33,7 @@ import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle 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.compound.tokens.generated.CompoundIcons @@ -41,8 +44,12 @@ 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.modifiers.onKeyboardContextMenuAction +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.ButtonSize import io.element.android.libraries.designsystem.theme.components.Icon 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.unreadIndicator import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.join.JoinRule @@ -59,6 +66,7 @@ fun SpaceRoomItemView( onClick: () -> Unit, onLongClick: () -> Unit, modifier: Modifier = Modifier, + trailingAction: @Composable (() -> Unit)? = null, ) { SpaceRoomItemScaffold( modifier = modifier, @@ -67,16 +75,14 @@ fun SpaceRoomItemView( hideAvatars = hideAvatars, onClick = onClick, onLongClick = onLongClick, + trailingAction = trailingAction, ) { NameAndIndicatorRow( - isSpace = spaceRoom.isSpace, - name = spaceRoom.name, - showIndicator = showUnreadIndicator + isSpace = spaceRoom.isSpace, name = spaceRoom.name, showIndicator = showUnreadIndicator ) Spacer(modifier = Modifier.height(1.dp)) SubtitleRow( - visibilityIcon = spaceRoom.visibilityIcon(), - subtitle = spaceRoom.subtitle() + visibilityIcon = spaceRoom.visibilityIcon(), subtitle = spaceRoom.subtitle() ) Spacer(modifier = Modifier.height(1.dp)) Text( @@ -166,7 +172,8 @@ private fun SpaceRoomItemScaffold( onLongClick: () -> Unit, hideAvatars: Boolean, modifier: Modifier = Modifier, - content: @Composable ColumnScope.() -> Unit + trailingAction: @Composable (() -> Unit)? = null, + content: @Composable ColumnScope.() -> Unit, ) { val clickModifier = Modifier .combinedClickable( @@ -174,8 +181,7 @@ private fun SpaceRoomItemScaffold( onLongClick = onLongClick, onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), indication = ripple(), - interactionSource = remember { MutableInteractionSource() } - ) + interactionSource = remember { MutableInteractionSource() }) .onKeyboardContextMenuAction { onLongClick } Row( modifier = modifier @@ -194,6 +200,10 @@ private fun SpaceRoomItemScaffold( modifier = Modifier.weight(1f), content = content, ) + if (trailingAction != null) { + Spacer(modifier = Modifier.width(16.dp)) + trailingAction() + } } } @@ -233,3 +243,16 @@ private fun SpaceRoom.visibilityIcon(): ImageVector? { CompoundIcons.LockSolid() } } + +@Composable +@PreviewsDayNight +internal fun SpaceRoomItemViewPreview(@PreviewParameter(SpaceRoomProvider::class) spaceRoom: SpaceRoom) = ElementPreview { + SpaceRoomItemView( + spaceRoom = spaceRoom, + showUnreadIndicator = spaceRoom.state == CurrentUserMembership.INVITED, + hideAvatars = false, + onClick = {}, + onLongClick = {}, + modifier = Modifier.fillMaxWidth() + ) +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomProvider.kt new file mode 100644 index 0000000000..c1c2700889 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomProvider.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.ui.components + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +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.room.RoomType +import io.element.android.libraries.matrix.api.spaces.SpaceRoom +import io.element.android.libraries.previewutils.room.aSpaceRoom + +class SpaceRoomProvider : PreviewParameterProvider { + override val values: Sequence = sequenceOf( + aSpaceRoom( + roomType = RoomType.Room, + name = "Room name", + topic = "Room topic that is quite long and might be truncated" + ), + aSpaceRoom( + numJoinedMembers = 5, + childrenCount = 10, + worldReadable = true, + roomId = RoomId("!spaceId0:example.com"), + ), + aSpaceRoom( + numJoinedMembers = 5, + childrenCount = 10, + worldReadable = true, + avatarUrl = "anUrl", + roomId = RoomId("!spaceId1:example.com"), + ), + aSpaceRoom( + name = null, + numJoinedMembers = 5, + childrenCount = 10, + worldReadable = true, + avatarUrl = "anUrl", + roomId = RoomId("!spaceId2:example.com"), + state = CurrentUserMembership.INVITED, + ), + aSpaceRoom( + name = null, + numJoinedMembers = 5, + childrenCount = 10, + worldReadable = true, + avatarUrl = "anUrl", + roomId = RoomId("!spaceId3:example.com"), + state = CurrentUserMembership.INVITED, + ), + ) +}