refactor (start chat) : properly finish create room flow

This commit is contained in:
ganfra
2025-08-08 19:23:46 +02:00
committed by Benoit Marty
parent c41994ad13
commit 5bbfaad03b
6 changed files with 89 additions and 11 deletions

View File

@@ -7,6 +7,22 @@
package io.element.android.features.createroom.api
import io.element.android.libraries.architecture.SimpleFeatureEntryPoint
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import io.element.android.libraries.architecture.FeatureEntryPoint
import io.element.android.libraries.matrix.api.core.RoomId
interface CreateRoomEntryPoint: SimpleFeatureEntryPoint
interface CreateRoomEntryPoint : FeatureEntryPoint {
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
interface NodeBuilder {
fun callback(callback: Callback): NodeBuilder
fun build(): Node
}
interface Callback: Plugin {
fun onRoomCreated(roomId: RoomId)
}
}

View File

@@ -13,12 +13,13 @@ import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import com.bumble.appyx.navmodel.backstack.BackStack
import com.bumble.appyx.navmodel.backstack.operation.push
import com.bumble.appyx.navmodel.backstack.operation.replace
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.createroom.api.CreateRoomEntryPoint
import io.element.android.features.createroom.impl.addpeople.AddPeopleNode
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
import io.element.android.libraries.architecture.BackstackView
@@ -44,6 +45,10 @@ class CreateRoomFlowNode @AssistedInject constructor(
plugins = plugins
) {
private fun onRoomCreated(roomId: RoomId) {
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onRoomCreated(roomId) }
}
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) {
NavTarget.ConfigureRoom -> {
@@ -57,7 +62,12 @@ class CreateRoomFlowNode @AssistedInject constructor(
is NavTarget.AddPeople -> {
val joinedRoom = runBlocking { client.getJoinedRoom(navTarget.roomId) } ?: error("Room not found")
val inputs = AddPeopleNode.Inputs(joinedRoom)
createNode<AddPeopleNode>(buildContext, plugins = listOf(inputs))
val callback: AddPeopleNode.Callback = object : AddPeopleNode.Callback {
override fun onFinish() {
onRoomCreated(navTarget.roomId)
}
}
createNode<AddPeopleNode>(buildContext, plugins = listOf(inputs, callback))
}
}
}

View File

@@ -9,6 +9,7 @@ package io.element.android.features.createroom.impl
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.createroom.api.CreateRoomEntryPoint
import io.element.android.libraries.architecture.createNode
@@ -16,8 +17,21 @@ import io.element.android.libraries.di.SessionScope
import javax.inject.Inject
@ContributesBinding(SessionScope::class)
class DefaultCreateRoomEntryPoint @Inject constructor(): CreateRoomEntryPoint {
override fun createNode(parentNode: Node, buildContext: BuildContext): Node {
return parentNode.createNode<CreateRoomFlowNode>(buildContext)
class DefaultCreateRoomEntryPoint @Inject constructor() : CreateRoomEntryPoint {
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): CreateRoomEntryPoint.NodeBuilder {
val plugins = ArrayList<Plugin>()
return object : CreateRoomEntryPoint.NodeBuilder {
override fun callback(callback: CreateRoomEntryPoint.Callback): CreateRoomEntryPoint.NodeBuilder {
plugins += callback
return this
}
override fun build(): Node {
return parentNode.createNode<CreateRoomFlowNode>(buildContext, plugins)
}
}
}
}

View File

@@ -12,6 +12,7 @@ import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
@@ -34,6 +35,14 @@ class AddPeopleNode @AssistedInject constructor(
val joinedRoom: JoinedRoom
) : NodeInputs
interface Callback : Plugin {
fun onFinish()
}
private fun onFinish() {
plugins<Callback>().forEach { it.onFinish() }
}
private val joinedRoom = inputs<Inputs>().joinedRoom
private val invitePeoplePresenter = invitePeoplePresenterFactory.create(joinedRoom)
@@ -43,7 +52,7 @@ class AddPeopleNode @AssistedInject constructor(
AddPeopleView(
state = state,
invitePeopleView = { invitePeopleRenderer.Render(state, Modifier) },
onFinish = {}
onFinish = ::onFinish
)
}
}

View File

@@ -8,15 +8,20 @@
package io.element.android.features.createroom.impl.addpeople
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.invitepeople.api.InvitePeopleEvents
import io.element.android.features.invitepeople.api.InvitePeopleState
import io.element.android.features.invitepeople.api.InvitePeopleStateProvider
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar
@@ -38,9 +43,14 @@ fun AddPeopleView(
footer = {
Button(
text = "Finish",
onClick = { state.eventSink(InvitePeopleEvents.SendInvites) },
onClick = {
state.eventSink(InvitePeopleEvents.SendInvites)
onFinish()
},
enabled = state.canInvite,
modifier = Modifier.padding(bottom = 16.dp)
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp)
)
},
content = invitePeopleView
@@ -62,3 +72,13 @@ private fun AddPeopleTopBar(
}
)
}
@PreviewsDayNight
@Composable
internal fun AddPeopleViewPreview(@PreviewParameter(InvitePeopleStateProvider::class) state: InvitePeopleState) = ElementPreview {
AddPeopleView(
state = state,
invitePeopleView = {},
onFinish = {},
)
}

View File

@@ -31,6 +31,8 @@ import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.OverlayView
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import kotlinx.parcelize.Parcelize
@ContributesNode(SessionScope::class)
@@ -74,7 +76,14 @@ class StartChatFlowNode @AssistedInject constructor(
createNode<StartChatNode>(buildContext = buildContext, plugins = listOf(navigator))
}
NavTarget.NewRoom -> {
createRoomEntryPoint.createNode(parentNode = this, buildContext = buildContext)
val callback = object : CreateRoomEntryPoint.Callback {
override fun onRoomCreated(roomId: RoomId) {
navigator.onOpenRoom(roomId.toRoomIdOrAlias(), emptyList())
}
}
createRoomEntryPoint.nodeBuilder(parentNode = this, buildContext = buildContext)
.callback(callback)
.build()
}
NavTarget.JoinByAddress -> {
createNode<JoinRoomByAddressNode>(buildContext = buildContext, plugins = listOf(navigator))