From 5bbfaad03bd4468218f81e22b614083c2364b76f Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 8 Aug 2025 19:23:46 +0200 Subject: [PATCH] refactor (start chat) : properly finish create room flow --- .../createroom/api/CreateRoomEntryPoint.kt | 20 ++++++++++++++-- .../createroom/impl/CreateRoomFlowNode.kt | 14 +++++++++-- .../impl/DefaultCreateRoomEntryPoint.kt | 20 +++++++++++++--- .../impl/addpeople/AddPeopleNode.kt | 11 ++++++++- .../impl/addpeople/AddPeopleView.kt | 24 +++++++++++++++++-- .../startchat/impl/StartChatFlowNode.kt | 11 ++++++++- 6 files changed, 89 insertions(+), 11 deletions(-) diff --git a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt b/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt index 6b4f02c033..ad4aa75ac5 100644 --- a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt +++ b/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt @@ -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) + } +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt index c4d085b95c..d2f6ae7ad5 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt @@ -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().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(buildContext, plugins = listOf(inputs)) + val callback: AddPeopleNode.Callback = object : AddPeopleNode.Callback { + override fun onFinish() { + onRoomCreated(navTarget.roomId) + } + } + createNode(buildContext, plugins = listOf(inputs, callback)) } } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPoint.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPoint.kt index 95f80cdfcf..3281aa97f3 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPoint.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPoint.kt @@ -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(buildContext) +class DefaultCreateRoomEntryPoint @Inject constructor() : CreateRoomEntryPoint { + + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): CreateRoomEntryPoint.NodeBuilder { + + val plugins = ArrayList() + + return object : CreateRoomEntryPoint.NodeBuilder { + override fun callback(callback: CreateRoomEntryPoint.Callback): CreateRoomEntryPoint.NodeBuilder { + plugins += callback + return this + } + + override fun build(): Node { + return parentNode.createNode(buildContext, plugins) + } + } } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleNode.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleNode.kt index cba1516168..a5bd6e828b 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleNode.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleNode.kt @@ -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().forEach { it.onFinish() } + } + private val joinedRoom = 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 ) } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt index ddcdc7e9b1..d918b4a227 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt @@ -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 = {}, + ) +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/StartChatFlowNode.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/StartChatFlowNode.kt index 1f4ae758d4..a312b6fa84 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/StartChatFlowNode.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/StartChatFlowNode.kt @@ -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(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(buildContext = buildContext, plugins = listOf(navigator))