Merge pull request #5614 from element-hq/feature/fga/space_flow_inject_room
Misc : space flow inject room
This commit is contained in:
commit
83d8151012
29 changed files with 163 additions and 74 deletions
|
|
@ -62,7 +62,6 @@ import io.element.android.features.roomdirectory.api.RoomDescription
|
|||
import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint
|
||||
import io.element.android.features.securebackup.api.SecureBackupEntryPoint
|
||||
import io.element.android.features.share.api.ShareEntryPoint
|
||||
import io.element.android.features.space.api.SpaceEntryPoint
|
||||
import io.element.android.features.startchat.api.StartChatEntryPoint
|
||||
import io.element.android.features.userprofile.api.UserProfileEntryPoint
|
||||
import io.element.android.features.verifysession.api.IncomingVerificationEntryPoint
|
||||
|
|
@ -256,7 +255,7 @@ class LoggedInFlowNode(
|
|||
val serverNames: List<String> = emptyList(),
|
||||
val trigger: JoinedRoom.Trigger? = null,
|
||||
val roomDescription: RoomDescription? = null,
|
||||
val initialElement: RoomNavigationTarget = RoomNavigationTarget.Messages(),
|
||||
val initialElement: RoomNavigationTarget = RoomNavigationTarget.Root(),
|
||||
val targetId: UUID = UUID.randomUUID(),
|
||||
) : NavTarget
|
||||
|
||||
|
|
@ -358,7 +357,7 @@ class LoggedInFlowNode(
|
|||
roomIdOrAlias = data.roomIdOrAlias,
|
||||
serverNames = data.viaParameters,
|
||||
trigger = JoinedRoom.Trigger.Timeline,
|
||||
initialElement = RoomNavigationTarget.Messages(data.eventId),
|
||||
initialElement = RoomNavigationTarget.Root(data.eventId),
|
||||
)
|
||||
if (pushToBackstack) {
|
||||
backstack.push(target)
|
||||
|
|
@ -377,11 +376,6 @@ class LoggedInFlowNode(
|
|||
backstack.push(NavTarget.Settings(PreferencesEntryPoint.InitialTarget.NotificationSettings))
|
||||
}
|
||||
}
|
||||
val spaceCallback = object : SpaceEntryPoint.Callback {
|
||||
override fun onOpenRoom(roomId: RoomId, viaParameters: List<String>) {
|
||||
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), serverNames = viaParameters))
|
||||
}
|
||||
}
|
||||
val inputs = RoomFlowNode.Inputs(
|
||||
roomIdOrAlias = navTarget.roomIdOrAlias,
|
||||
roomDescription = Optional.ofNullable(navTarget.roomDescription),
|
||||
|
|
@ -389,7 +383,7 @@ class LoggedInFlowNode(
|
|||
trigger = Optional.ofNullable(navTarget.trigger),
|
||||
initialElement = navTarget.initialElement
|
||||
)
|
||||
createNode<RoomFlowNode>(buildContext, plugins = listOf(inputs, joinedRoomCallback, spaceCallback))
|
||||
createNode<RoomFlowNode>(buildContext, plugins = listOf(inputs, joinedRoomCallback))
|
||||
}
|
||||
is NavTarget.UserProfile -> {
|
||||
val callback = object : UserProfileEntryPoint.Callback {
|
||||
|
|
@ -421,7 +415,7 @@ class LoggedInFlowNode(
|
|||
}
|
||||
|
||||
override fun navigateTo(roomId: RoomId, eventId: EventId) {
|
||||
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), initialElement = RoomNavigationTarget.Messages(eventId)))
|
||||
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias(), initialElement = RoomNavigationTarget.Root(eventId)))
|
||||
}
|
||||
}
|
||||
val inputs = PreferencesEntryPoint.Params(navTarget.initialElement)
|
||||
|
|
@ -516,9 +510,7 @@ class LoggedInFlowNode(
|
|||
roomIdOrAlias = roomIdOrAlias,
|
||||
serverNames = serverNames,
|
||||
trigger = trigger,
|
||||
initialElement = RoomNavigationTarget.Messages(
|
||||
focusedEventId = eventId
|
||||
)
|
||||
initialElement = RoomNavigationTarget.Root(eventId = eventId)
|
||||
)
|
||||
backstack.accept(AttachRoomOperation(roomNavTarget, clearBackstack))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ package io.element.android.appnav.room
|
|||
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.bumble.appyx.core.modality.BuildContext
|
||||
|
|
@ -37,7 +36,6 @@ import io.element.android.libraries.architecture.BaseFlowNode
|
|||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.core.coroutine.withPreviousValue
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
|
|
@ -49,11 +47,11 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
|||
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||
import io.element.android.libraries.matrix.ui.room.LoadingRoomState
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
|
@ -130,7 +128,6 @@ class RoomFlowNode(
|
|||
|
||||
private fun subscribeToRoomInfoFlow(roomId: RoomId, serverNames: List<String>) {
|
||||
val roomInfoFlow = client.getRoomInfoFlow(roomId)
|
||||
val isSpaceFlow = roomInfoFlow.map { it.getOrNull()?.isSpace.orFalse() }.distinctUntilChanged()
|
||||
|
||||
// This observes the local membership changes for the room
|
||||
val membershipUpdateFlow = membershipObserver.updates
|
||||
|
|
@ -143,14 +140,10 @@ class RoomFlowNode(
|
|||
.map { it.getOrNull()?.currentUserMembership }
|
||||
.distinctUntilChanged()
|
||||
.withPreviousValue()
|
||||
combine(currentMembershipFlow, isSpaceFlow) { (previousMembership, membership), isSpace ->
|
||||
currentMembershipFlow.onEach { (previousMembership, membership) ->
|
||||
Timber.d("Room membership: $membership")
|
||||
if (membership == CurrentUserMembership.JOINED) {
|
||||
if (isSpace) {
|
||||
backstack.newRoot(NavTarget.JoinedSpace(spaceId = roomId))
|
||||
} else {
|
||||
backstack.newRoot(NavTarget.JoinedRoom(roomId))
|
||||
}
|
||||
backstack.newRoot(NavTarget.JoinedRoom(roomId))
|
||||
} else {
|
||||
val leavingFromCurrentDevice =
|
||||
membership == CurrentUserMembership.LEFT &&
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import kotlinx.parcelize.Parcelize
|
|||
|
||||
sealed interface RoomNavigationTarget : Parcelable {
|
||||
@Parcelize
|
||||
data class Messages(val focusedEventId: EventId? = null) : RoomNavigationTarget
|
||||
data class Root(val eventId: EventId? = null) : RoomNavigationTarget
|
||||
|
||||
@Parcelize
|
||||
data object Details : RoomNavigationTarget
|
||||
|
|
|
|||
|
|
@ -22,8 +22,11 @@ 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
|
||||
import io.element.android.libraries.architecture.BackstackView
|
||||
import io.element.android.libraries.architecture.BaseFlowNode
|
||||
import io.element.android.libraries.architecture.NodeInputs
|
||||
|
|
@ -51,6 +54,7 @@ class JoinedRoomLoadedFlowNode(
|
|||
@Assisted plugins: List<Plugin>,
|
||||
private val messagesEntryPoint: MessagesEntryPoint,
|
||||
private val roomDetailsEntryPoint: RoomDetailsEntryPoint,
|
||||
private val spaceEntryPoint: SpaceEntryPoint,
|
||||
private val appNavigationStateService: AppNavigationStateService,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
|
|
@ -59,11 +63,7 @@ class JoinedRoomLoadedFlowNode(
|
|||
roomGraphFactory: RoomGraphFactory,
|
||||
) : BaseFlowNode<JoinedRoomLoadedFlowNode.NavTarget>(
|
||||
backstack = BackStack(
|
||||
initialElement = when (val input = plugins.filterIsInstance<Inputs>().first().initialElement) {
|
||||
is RoomNavigationTarget.Messages -> NavTarget.Messages(input.focusedEventId)
|
||||
RoomNavigationTarget.Details -> NavTarget.RoomDetails
|
||||
RoomNavigationTarget.NotificationSettings -> NavTarget.RoomNotificationSettings
|
||||
},
|
||||
initialElement = initialElement(plugins),
|
||||
savedStateMap = buildContext.savedStateMap,
|
||||
),
|
||||
buildContext = buildContext,
|
||||
|
|
@ -154,9 +154,28 @@ class JoinedRoomLoadedFlowNode(
|
|||
NavTarget.RoomNotificationSettings -> {
|
||||
createRoomDetailsNode(buildContext, RoomDetailsEntryPoint.InitialTarget.RoomNotificationSettings)
|
||||
}
|
||||
NavTarget.Space -> {
|
||||
createSpaceNode(buildContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSpaceNode(buildContext: BuildContext): Node {
|
||||
val callback = object : SpaceEntryPoint.Callback {
|
||||
override fun onOpenRoom(roomId: RoomId, viaParameters: List<String>) {
|
||||
callbacks.forEach { it.onOpenRoom(roomId, viaParameters) }
|
||||
}
|
||||
|
||||
override fun onOpenDetails() {
|
||||
backstack.push(NavTarget.RoomDetails)
|
||||
}
|
||||
}
|
||||
return spaceEntryPoint.nodeBuilder(this, buildContext)
|
||||
.inputs(SpaceEntryPoint.Inputs(roomId = inputs.room.roomId))
|
||||
.callback(callback)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun createMessagesNode(
|
||||
buildContext: BuildContext,
|
||||
navTarget: NavTarget.Messages,
|
||||
|
|
@ -188,6 +207,9 @@ class JoinedRoomLoadedFlowNode(
|
|||
}
|
||||
|
||||
sealed interface NavTarget : Parcelable {
|
||||
@Parcelize
|
||||
data object Space : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data class Messages(val focusedEventId: EventId? = null) : NavTarget
|
||||
|
||||
|
|
@ -206,3 +228,18 @@ class JoinedRoomLoadedFlowNode(
|
|||
BackstackView()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initialElement(plugins: List<Plugin>): NavTarget {
|
||||
val input = plugins.filterIsInstance<Inputs>().single()
|
||||
return when (input.initialElement) {
|
||||
is RoomNavigationTarget.Root -> {
|
||||
if (input.room.roomInfoFlow.value.isSpace) {
|
||||
NavTarget.Space
|
||||
} else {
|
||||
NavTarget.Messages(input.initialElement.eventId)
|
||||
}
|
||||
}
|
||||
RoomNavigationTarget.Details -> NavTarget.RoomDetails
|
||||
RoomNavigationTarget.NotificationSettings -> NavTarget.RoomNotificationSettings
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
|
|
@ -76,7 +74,6 @@ private fun LoadingRoomTopBar(
|
|||
BackButton(onClick = onBackClick)
|
||||
},
|
||||
title = {
|
||||
IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ import io.element.android.appnav.room.RoomNavigationTarget
|
|||
import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode
|
||||
import io.element.android.features.messages.api.MessagesEntryPoint
|
||||
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint
|
||||
import io.element.android.features.space.api.SpaceEntryPoint
|
||||
import io.element.android.libraries.architecture.childNode
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
|
||||
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
|
||||
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
||||
import io.element.android.services.appnavstate.api.ActiveRoomsHolder
|
||||
import io.element.android.services.appnavstate.test.FakeAppNavigationStateService
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
|
|
@ -98,16 +100,40 @@ class JoinedRoomLoadedFlowNodeTest {
|
|||
}
|
||||
}
|
||||
|
||||
private class FakeSpaceEntryPoint : SpaceEntryPoint {
|
||||
var nodeId: String? = null
|
||||
|
||||
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): SpaceEntryPoint.NodeBuilder {
|
||||
return object : SpaceEntryPoint.NodeBuilder {
|
||||
override fun inputs(inputs: SpaceEntryPoint.Inputs): SpaceEntryPoint.NodeBuilder {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun callback(callback: SpaceEntryPoint.Callback): SpaceEntryPoint.NodeBuilder {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun build(): Node {
|
||||
return node(buildContext) {}.also {
|
||||
nodeId = it.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun TestScope.createJoinedRoomLoadedFlowNode(
|
||||
plugins: List<Plugin>,
|
||||
messagesEntryPoint: MessagesEntryPoint = FakeMessagesEntryPoint(),
|
||||
roomDetailsEntryPoint: RoomDetailsEntryPoint = FakeRoomDetailsEntryPoint(),
|
||||
spaceEntryPoint: SpaceEntryPoint = FakeSpaceEntryPoint(),
|
||||
activeRoomsHolder: ActiveRoomsHolder = ActiveRoomsHolder(),
|
||||
) = JoinedRoomLoadedFlowNode(
|
||||
buildContext = BuildContext.root(savedStateMap = null),
|
||||
plugins = plugins,
|
||||
messagesEntryPoint = messagesEntryPoint,
|
||||
roomDetailsEntryPoint = roomDetailsEntryPoint,
|
||||
spaceEntryPoint = spaceEntryPoint,
|
||||
appNavigationStateService = FakeAppNavigationStateService(),
|
||||
sessionCoroutineScope = this,
|
||||
roomGraphFactory = FakeRoomGraphFactory(),
|
||||
|
|
@ -116,11 +142,11 @@ class JoinedRoomLoadedFlowNodeTest {
|
|||
)
|
||||
|
||||
@Test
|
||||
fun `given a room flow node when initialized then it loads messages entry point`() = runTest {
|
||||
fun `given a room flow node when initialized then it loads messages entry point if room is not space`() = runTest {
|
||||
// GIVEN
|
||||
val room = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {}))
|
||||
val room = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {}, initialRoomInfo = aRoomInfo(isSpace = false)))
|
||||
val fakeMessagesEntryPoint = FakeMessagesEntryPoint()
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Messages())
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Root())
|
||||
val roomFlowNode = createJoinedRoomLoadedFlowNode(
|
||||
plugins = listOf(inputs),
|
||||
messagesEntryPoint = fakeMessagesEntryPoint,
|
||||
|
|
@ -135,13 +161,33 @@ class JoinedRoomLoadedFlowNodeTest {
|
|||
assertThat(messagesNode.id).isEqualTo(fakeMessagesEntryPoint.nodeId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a room flow node when initialized then it loads space entry point if room is space`() = runTest {
|
||||
// GIVEN
|
||||
val room = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {}, initialRoomInfo = aRoomInfo(isSpace = true)))
|
||||
val spaceEntryPoint = FakeSpaceEntryPoint()
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Root())
|
||||
val roomFlowNode = createJoinedRoomLoadedFlowNode(
|
||||
plugins = listOf(inputs),
|
||||
spaceEntryPoint = spaceEntryPoint,
|
||||
)
|
||||
// WHEN
|
||||
val roomFlowNodeTestHelper = roomFlowNode.parentNodeTestHelper()
|
||||
|
||||
// THEN
|
||||
assertThat(roomFlowNode.backstack.activeElement).isEqualTo(JoinedRoomLoadedFlowNode.NavTarget.Space)
|
||||
roomFlowNodeTestHelper.assertChildHasLifecycle(JoinedRoomLoadedFlowNode.NavTarget.Space, Lifecycle.State.CREATED)
|
||||
val spaceNode = roomFlowNode.childNode(JoinedRoomLoadedFlowNode.NavTarget.Space)!!
|
||||
assertThat(spaceNode.id).isEqualTo(spaceEntryPoint.nodeId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a room flow node when callback on room details is triggered then it loads room details entry point`() = runTest {
|
||||
// GIVEN
|
||||
val room = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {}))
|
||||
val fakeMessagesEntryPoint = FakeMessagesEntryPoint()
|
||||
val fakeRoomDetailsEntryPoint = FakeRoomDetailsEntryPoint()
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Messages())
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Root())
|
||||
val roomFlowNode = createJoinedRoomLoadedFlowNode(
|
||||
plugins = listOf(inputs),
|
||||
messagesEntryPoint = fakeMessagesEntryPoint,
|
||||
|
|
@ -162,7 +208,7 @@ class JoinedRoomLoadedFlowNodeTest {
|
|||
val room = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {}))
|
||||
val fakeMessagesEntryPoint = FakeMessagesEntryPoint()
|
||||
val fakeRoomDetailsEntryPoint = FakeRoomDetailsEntryPoint()
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Messages())
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Root())
|
||||
val activeRoomsHolder = ActiveRoomsHolder()
|
||||
val roomFlowNode = createJoinedRoomLoadedFlowNode(
|
||||
plugins = listOf(inputs),
|
||||
|
|
@ -185,7 +231,7 @@ class JoinedRoomLoadedFlowNodeTest {
|
|||
val room = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {}))
|
||||
val fakeMessagesEntryPoint = FakeMessagesEntryPoint()
|
||||
val fakeRoomDetailsEntryPoint = FakeRoomDetailsEntryPoint()
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Messages())
|
||||
val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Root())
|
||||
val activeRoomsHolder = ActiveRoomsHolder().apply {
|
||||
addRoom(room)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,5 +32,6 @@ interface SpaceEntryPoint : FeatureEntryPoint {
|
|||
|
||||
interface Callback : Plugin {
|
||||
fun onOpenRoom(roomId: RoomId, viaParameters: List<String>)
|
||||
fun onOpenDetails()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ import io.element.android.libraries.architecture.BaseFlowNode
|
|||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.di.DependencyInjectionGraphOwner
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceService
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@ContributesNode(SessionScope::class)
|
||||
@ContributesNode(RoomScope::class)
|
||||
@AssistedInject
|
||||
class SpaceFlowNode(
|
||||
@Assisted val buildContext: BuildContext,
|
||||
|
|
@ -84,6 +84,10 @@ class SpaceFlowNode(
|
|||
callback.onOpenRoom(roomId, viaParameters)
|
||||
}
|
||||
|
||||
override fun onOpenDetails() {
|
||||
callback.onOpenDetails()
|
||||
}
|
||||
|
||||
override fun onLeaveSpace() {
|
||||
backstack.push(NavTarget.Leave)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ import dev.zacsweers.metro.ContributesTo
|
|||
import dev.zacsweers.metro.GraphExtension
|
||||
import dev.zacsweers.metro.Provides
|
||||
import io.element.android.libraries.architecture.NodeFactoriesBindings
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
|
||||
|
||||
@GraphExtension(SpaceFlowScope::class)
|
||||
interface SpaceFlowGraph : NodeFactoriesBindings {
|
||||
@ContributesTo(SessionScope::class)
|
||||
@ContributesTo(RoomScope::class)
|
||||
@GraphExtension.Factory
|
||||
interface Factory {
|
||||
fun create(@Provides spaceRoomList: SpaceRoomList): SpaceFlowGraph
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class SpaceNode(
|
|||
) : Node(buildContext, plugins = plugins) {
|
||||
interface Callback : Plugin {
|
||||
fun onOpenRoom(roomId: RoomId, viaParameters: List<String>)
|
||||
fun onOpenDetails()
|
||||
fun onLeaveSpace()
|
||||
}
|
||||
|
||||
|
|
@ -76,6 +77,9 @@ class SpaceNode(
|
|||
onRoomClick = { spaceRoom ->
|
||||
callback.onOpenRoom(spaceRoom.roomId, spaceRoom.via)
|
||||
},
|
||||
onDetailsClick = {
|
||||
callback.onOpenDetails()
|
||||
},
|
||||
onShareSpace = {
|
||||
onShareRoom(context)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.features.space.impl.root
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
|
@ -15,6 +16,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
|
|
@ -25,6 +27,7 @@ import androidx.compose.runtime.rememberUpdatedState
|
|||
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.res.stringResource
|
||||
import androidx.compose.ui.semantics.heading
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
|
|
@ -74,6 +77,7 @@ fun SpaceView(
|
|||
onRoomClick: (spaceRoom: SpaceRoom) -> Unit,
|
||||
onShareSpace: () -> Unit,
|
||||
onLeaveSpaceClick: () -> Unit,
|
||||
onDetailsClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
acceptDeclineInviteView: @Composable () -> Unit,
|
||||
) {
|
||||
|
|
@ -85,6 +89,7 @@ fun SpaceView(
|
|||
onBackClick = onBackClick,
|
||||
onLeaveSpaceClick = onLeaveSpaceClick,
|
||||
onShareSpace = onShareSpace,
|
||||
onDetailsClick = onDetailsClick
|
||||
)
|
||||
},
|
||||
content = { padding ->
|
||||
|
|
@ -249,6 +254,7 @@ private fun SpaceViewTopBar(
|
|||
currentSpace: SpaceRoom?,
|
||||
onBackClick: () -> Unit,
|
||||
onLeaveSpaceClick: () -> Unit,
|
||||
onDetailsClick: () -> Unit,
|
||||
onShareSpace: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -259,9 +265,14 @@ private fun SpaceViewTopBar(
|
|||
},
|
||||
title = {
|
||||
if (currentSpace != null) {
|
||||
val roundedCornerShape = RoundedCornerShape(8.dp)
|
||||
SpaceAvatarAndNameRow(
|
||||
name = currentSpace.displayName,
|
||||
avatarData = currentSpace.getAvatarData(AvatarSize.TimelineRoom),
|
||||
modifier = Modifier
|
||||
.clip(roundedCornerShape)
|
||||
// TODO enable when screen ready for space
|
||||
.clickable(enabled = false, onClick = onDetailsClick)
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
@ -391,6 +402,7 @@ internal fun SpaceViewPreview(
|
|||
onShareSpace = {},
|
||||
onLeaveSpaceClick = {},
|
||||
acceptDeclineInviteView = {},
|
||||
onDetailsClick = {},
|
||||
onBackClick = {},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class DefaultSpaceEntryPointTest {
|
|||
}
|
||||
val callback = object : SpaceEntryPoint.Callback {
|
||||
override fun onOpenRoom(roomId: RoomId, viaParameters: List<String>) = lambdaError()
|
||||
override fun onOpenDetails() = lambdaError()
|
||||
}
|
||||
val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null))
|
||||
.inputs(nodeInputs)
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setSpace
|
|||
onRoomClick: (SpaceRoom) -> Unit = EnsureNeverCalledWithParam(),
|
||||
onShareSpace: () -> Unit = EnsureNeverCalled(),
|
||||
onLeaveSpaceClick: () -> Unit = EnsureNeverCalled(),
|
||||
onDetailsClick: () -> Unit = EnsureNeverCalled(),
|
||||
acceptDeclineInviteView: @Composable () -> Unit = {},
|
||||
) {
|
||||
setContent {
|
||||
|
|
@ -148,6 +149,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setSpace
|
|||
onRoomClick = onRoomClick,
|
||||
onShareSpace = onShareSpace,
|
||||
onLeaveSpaceClick = onLeaveSpaceClick,
|
||||
onDetailsClick = onDetailsClick,
|
||||
acceptDeclineInviteView = acceptDeclineInviteView,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c9583a29e680bee98819258e5b7356dd8677144957d5869da72c47685d986e87
|
||||
size 6494
|
||||
oid sha256:071914fc3e7bbc2fc6ef8a1b4544b9126c05dd08b2123666d320223582423226
|
||||
size 5632
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f5c19a8b26c9187c9bfd630242b15370ec8f0b874f9d3913ce53c743c0e0bdcd
|
||||
size 8574
|
||||
oid sha256:5e9df6017bd0771e1337f82b75d13a0a8a572156e6900ae72f208e9bb2aaddb7
|
||||
size 7717
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:74ad11143fc70164f67a8326cb87ce90a2c8730317540810ea138e39fc9093fa
|
||||
size 6306
|
||||
oid sha256:811bd4534f4f16530cea1489b62d393e2fe7bf1b18b859a924333cd9d309f8dd
|
||||
size 5566
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bde612ade7298aeef44bbc480ee9d742ccb8c94108e21dcae9e804c744032a08
|
||||
size 8308
|
||||
oid sha256:030971f2c5f8c19f47fed2fa207c6d84d536c603fa7705ea6c288736684b7868
|
||||
size 7553
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ba78cafc20c3d865fec9c7ab92f90e2565f233b224f99fb0665ad0d0c3c2be4e
|
||||
size 34607
|
||||
oid sha256:c55277089a4447b618a0e8c058718ecf9d3da6d437322f0e23e5fd70019f6b00
|
||||
size 34585
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fe62bb5d157ba1b4c7a4e4f443f4b1b3e7d68bc0ac59ce7edb6fbc99e2abbdf7
|
||||
size 34795
|
||||
oid sha256:241f5500cb7212fac174466bbe7855ccf39de3e3764a83202388b947d90ae807
|
||||
size 34770
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:88db0bd5d05963761bd3b3a5a97834f8937a9a0e10723238f2c104c5d03eb81a
|
||||
size 35089
|
||||
oid sha256:92785cf3a4010779b0fbcd58be3437a22808b0a2f02a19a5cfd50eb3bd58ed26
|
||||
size 35058
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7e8b65396dedff81056157620e2390c8d69954ee288266b575ac61aba16c2bec
|
||||
size 62590
|
||||
oid sha256:de26882f13bac98b2cb5365d98e06e781d516d179adb8328cf22cf524e6fd79e
|
||||
size 62568
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b8e1fb3b8b62ea8583a5bc9a18f39dbe71684e7d019bf63b22b873851b219209
|
||||
size 63270
|
||||
oid sha256:a121fdb9473512b0264e48294df1799a7a6bf9b469df973fbe41f31bbf98f1d0
|
||||
size 63248
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3e60857b4c0d801d3a6ad7f7383b8ff8428157763ca46d30c2a559a4957cb71e
|
||||
size 59706
|
||||
oid sha256:a3506b4f646408262450ae51b612f86c1171ed972c1d7ea8871c4dc090556c7a
|
||||
size 59702
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:53b3736b922b746a996f71aa38b3937ebc16e37eb40bb57cd1991d6f9d98ea33
|
||||
size 34022
|
||||
oid sha256:f2407444889af236ef21a90c47a5d3e05df8b15b9cc9483e84377e3af8794772
|
||||
size 33996
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4f2d6b368d4a8eaa8f3a396ba6edf8252d52b0e7ebd3b3f416c60050d3cd3c57
|
||||
size 34170
|
||||
oid sha256:fee41efefc2ca1d6670d8455ac756c6b314aab54510eab8a4e597f1cc1edf3f8
|
||||
size 34141
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4b0b347f48ac09d05a2348383580d26e3725af2ef48558be86541afa239f3b06
|
||||
size 34485
|
||||
oid sha256:ea955839cbd1aeba5de2780cee413628c7d46383398b10125cd3a900fb41d5a5
|
||||
size 34459
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9ff5ca08d441240de9e5adc35e41bceeb0f462979777345da4b2865e9a80012e
|
||||
size 61405
|
||||
oid sha256:cba2c99744aeb2a869ae2ed700d7241b1d0b6ed979b16d2be9774ddbc5f8f28a
|
||||
size 61381
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2f35b63ac49c799a5b3b5ad47652fe0f199efbbd2a285f782170c1edcd9ae723
|
||||
size 61955
|
||||
oid sha256:b32d65accabc357208efeb2ec61374182479541299ade28184f82938e59bfdd5
|
||||
size 61932
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f470577ca0f0de530db1ab0d531f5b14630f9082cc4c34ad4e3fcbc1ab9ee530
|
||||
size 57954
|
||||
oid sha256:7c161ff55e8a235fe403e53ee179b299fd2563d85ef64bfe6d0dd9295228685b
|
||||
size 57925
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue