diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt index 93e0c64a7f..aab9590a9b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt @@ -22,8 +22,6 @@ import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode import io.element.android.appnav.di.RoomGraphFactory import io.element.android.appnav.room.RoomNavigationTarget -import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode.Inputs -import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode.NavTarget import io.element.android.features.messages.api.MessagesEntryPoint import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint import io.element.android.features.space.api.SpaceEntryPoint @@ -154,6 +152,9 @@ class JoinedRoomLoadedFlowNode( NavTarget.RoomNotificationSettings -> { createRoomDetailsNode(buildContext, RoomDetailsEntryPoint.InitialTarget.RoomNotificationSettings) } + NavTarget.RoomMemberList -> { + createRoomDetailsNode(buildContext, RoomDetailsEntryPoint.InitialTarget.RoomMemberList) + } NavTarget.Space -> { createSpaceNode(buildContext) } @@ -169,6 +170,10 @@ class JoinedRoomLoadedFlowNode( override fun onOpenDetails() { backstack.push(NavTarget.RoomDetails) } + + override fun onOpenMemberList() { + backstack.push(NavTarget.RoomMemberList) + } } return spaceEntryPoint.nodeBuilder(this, buildContext) .inputs(SpaceEntryPoint.Inputs(roomId = inputs.room.roomId)) @@ -216,6 +221,9 @@ class JoinedRoomLoadedFlowNode( @Parcelize data object RoomDetails : NavTarget + @Parcelize + data object RoomMemberList : NavTarget + @Parcelize data class RoomMemberDetails(val userId: UserId) : NavTarget @@ -229,17 +237,17 @@ class JoinedRoomLoadedFlowNode( } } -private fun initialElement(plugins: List): NavTarget { - val input = plugins.filterIsInstance().single() +private fun initialElement(plugins: List): JoinedRoomLoadedFlowNode.NavTarget { + val input = plugins.filterIsInstance().single() return when (input.initialElement) { is RoomNavigationTarget.Root -> { if (input.room.roomInfoFlow.value.isSpace) { - NavTarget.Space + JoinedRoomLoadedFlowNode.NavTarget.Space } else { - NavTarget.Messages(input.initialElement.eventId) + JoinedRoomLoadedFlowNode.NavTarget.Messages(input.initialElement.eventId) } } - RoomNavigationTarget.Details -> NavTarget.RoomDetails - RoomNavigationTarget.NotificationSettings -> NavTarget.RoomNotificationSettings + RoomNavigationTarget.Details -> JoinedRoomLoadedFlowNode.NavTarget.RoomDetails + RoomNavigationTarget.NotificationSettings -> JoinedRoomLoadedFlowNode.NavTarget.RoomNotificationSettings } } diff --git a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt index 803002d642..0d725938f6 100644 --- a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt +++ b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt @@ -23,6 +23,9 @@ interface RoomDetailsEntryPoint : FeatureEntryPoint { @Parcelize data object RoomDetails : InitialTarget + @Parcelize + data object RoomMemberList : InitialTarget + @Parcelize data class RoomMemberDetails(val roomMemberId: UserId) : InitialTarget diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPoint.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPoint.kt index 0ae2dc09ea..5679b8c361 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPoint.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPoint.kt @@ -44,4 +44,5 @@ internal fun InitialTarget.toNavTarget() = when (this) { is InitialTarget.RoomDetails -> NavTarget.RoomDetails is InitialTarget.RoomMemberDetails -> NavTarget.RoomMemberDetails(roomMemberId) is InitialTarget.RoomNotificationSettings -> NavTarget.RoomNotificationSettings(showUserDefinedSettingStyle = true) + InitialTarget.RoomMemberList -> NavTarget.RoomMemberList } diff --git a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt index a5f1134bf3..9dd61c6dff 100644 --- a/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt +++ b/features/space/api/src/main/kotlin/io/element/android/features/space/api/SpaceEntryPoint.kt @@ -33,5 +33,7 @@ interface SpaceEntryPoint : FeatureEntryPoint { interface Callback : Plugin { fun onOpenRoom(roomId: RoomId, viaParameters: List) fun onOpenDetails() + + fun onOpenMemberList() } } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceFlowNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceFlowNode.kt index 833186958b..f73a3d31ff 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceFlowNode.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/SpaceFlowNode.kt @@ -88,6 +88,10 @@ class SpaceFlowNode( callback.onOpenDetails() } + override fun onOpenMemberList() { + callback.onOpenMemberList() + } + override fun onLeaveSpace() { backstack.push(NavTarget.Leave) } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceNode.kt index 5266ba9f46..f02107dad2 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceNode.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceNode.kt @@ -42,6 +42,8 @@ class SpaceNode( interface Callback : Plugin { fun onOpenRoom(roomId: RoomId, viaParameters: List) fun onOpenDetails() + + fun onOpenMemberList() fun onLeaveSpace() } @@ -83,6 +85,9 @@ class SpaceNode( onShareSpace = { onShareRoom(context) }, + onViewMembersClick = { + callback.onOpenMemberList() + }, acceptDeclineInviteView = { acceptDeclineInviteView.Render( state = state.acceptDeclineInviteState, diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt index b32f9b73e1..f4c415b718 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt @@ -78,6 +78,7 @@ fun SpaceView( onShareSpace: () -> Unit, onLeaveSpaceClick: () -> Unit, onDetailsClick: () -> Unit, + onViewMembersClick: () -> Unit, modifier: Modifier = Modifier, acceptDeclineInviteView: @Composable () -> Unit, ) { @@ -89,7 +90,8 @@ fun SpaceView( onBackClick = onBackClick, onLeaveSpaceClick = onLeaveSpaceClick, onShareSpace = onShareSpace, - onDetailsClick = onDetailsClick + onDetailsClick = onDetailsClick, + onViewMembersClick = onViewMembersClick, ) }, content = { padding -> @@ -256,6 +258,7 @@ private fun SpaceViewTopBar( onLeaveSpaceClick: () -> Unit, onDetailsClick: () -> Unit, onShareSpace: () -> Unit, + onViewMembersClick: () -> Unit, modifier: Modifier = Modifier, ) { TopAppBar( @@ -304,6 +307,20 @@ private fun SpaceViewTopBar( ) } ) + DropdownMenuItem( + onClick = { + showMenu = false + onViewMembersClick() + }, + text = { Text(stringResource(id = CommonStrings.screen_space_menu_action_members)) }, + leadingIcon = { + Icon( + imageVector = CompoundIcons.User(), + tint = ElementTheme.colors.iconSecondary, + contentDescription = null, + ) + } + ) DropdownMenuItem( onClick = { showMenu = false @@ -344,10 +361,10 @@ private fun SpaceAvatarAndNameRow( ) Text( modifier = Modifier - .padding(horizontal = 8.dp) - .semantics { - heading() - }, + .padding(horizontal = 8.dp) + .semantics { + heading() + }, text = name ?: stringResource(CommonStrings.common_no_space_name), style = ElementTheme.typography.fontBodyLgMedium, fontStyle = FontStyle.Italic.takeIf { name == null }, @@ -403,6 +420,7 @@ internal fun SpaceViewPreview( onLeaveSpaceClick = {}, acceptDeclineInviteView = {}, onDetailsClick = {}, + onViewMembersClick = {}, onBackClick = {}, ) } diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt index 13e24259dc..2d43ef0d39 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt @@ -46,6 +46,7 @@ class DefaultSpaceEntryPointTest { val callback = object : SpaceEntryPoint.Callback { override fun onOpenRoom(roomId: RoomId, viaParameters: List) = lambdaError() override fun onOpenDetails() = lambdaError() + override fun onOpenMemberList() = lambdaError() } val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) .inputs(nodeInputs) diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpaceViewTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpaceViewTest.kt index f8797916e4..44a06d378f 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpaceViewTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpaceViewTest.kt @@ -140,6 +140,7 @@ private fun AndroidComposeTestRule.setSpace onShareSpace: () -> Unit = EnsureNeverCalled(), onLeaveSpaceClick: () -> Unit = EnsureNeverCalled(), onDetailsClick: () -> Unit = EnsureNeverCalled(), + onViewMembersClick: () -> Unit = EnsureNeverCalled(), acceptDeclineInviteView: @Composable () -> Unit = {}, ) { setContent { @@ -150,6 +151,7 @@ private fun AndroidComposeTestRule.setSpace onShareSpace = onShareSpace, onLeaveSpaceClick = onLeaveSpaceClick, onDetailsClick = onDetailsClick, + onViewMembersClick = onViewMembersClick, acceptDeclineInviteView = acceptDeclineInviteView, ) }