Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature : join room by address #4302

Merged
merged 14 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,8 @@ class LoggedInFlowNode @AssistedInject constructor(
}
NavTarget.CreateRoom -> {
val callback = object : CreateRoomEntryPoint.Callback {
override fun onSuccess(roomId: RoomId) {
backstack.replace(NavTarget.Room(roomId.toRoomIdOrAlias()))
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) {
backstack.replace(NavTarget.Room(roomIdOrAlias = roomIdOrAlias, serverNames = serverNames))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ 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
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias

interface CreateRoomEntryPoint : FeatureEntryPoint {
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
Expand All @@ -21,6 +21,6 @@ interface CreateRoomEntryPoint : FeatureEntryPoint {
}

interface Callback : Plugin {
fun onSuccess(roomId: RoomId)
fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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.features.createroom

import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.navmodel.backstack.BackStack
import com.bumble.appyx.navmodel.backstack.operation.push
import io.element.android.features.createroom.impl.CreateRoomFlowNode.NavTarget
import io.element.android.libraries.architecture.overlay.Overlay
import io.element.android.libraries.architecture.overlay.operation.hide
import io.element.android.libraries.architecture.overlay.operation.show
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias

interface CreateRoomNavigator : Plugin {
fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>)
fun onCreateNewRoom()
fun onShowJoinRoomByAddress()
fun onDismissJoinRoomByAddress()
}

class DefaultCreateRoomNavigator(
private val backstack: BackStack<NavTarget>,
private val overlay: Overlay<NavTarget>,
private val openRoom: (RoomIdOrAlias, List<String>) -> Unit,

Check warning on line 29 in features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt

View check run for this annotation

Codecov / codecov/patch

features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt#L26-L29

Added lines #L26 - L29 were not covered by tests
) : CreateRoomNavigator {
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) = openRoom(roomIdOrAlias, serverNames)

Check warning on line 31 in features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt

View check run for this annotation

Codecov / codecov/patch

features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt#L31

Added line #L31 was not covered by tests

override fun onCreateNewRoom() {
backstack.push(NavTarget.NewRoom)

Check warning on line 34 in features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt

View check run for this annotation

Codecov / codecov/patch

features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt#L34

Added line #L34 was not covered by tests
}

override fun onShowJoinRoomByAddress() {
overlay.show(NavTarget.JoinByAddress)

Check warning on line 38 in features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt

View check run for this annotation

Codecov / codecov/patch

features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt#L38

Added line #L38 was not covered by tests
}

override fun onDismissJoinRoomByAddress() {
overlay.hide()

Check warning on line 42 in features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt

View check run for this annotation

Codecov / codecov/patch

features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt#L42

Added line #L42 was not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.createroom.CreateRoomNavigator
import io.element.android.features.createroom.impl.addpeople.AddPeopleNode
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
import io.element.android.features.createroom.impl.di.CreateRoomComponent
Expand Down Expand Up @@ -46,6 +47,7 @@ class ConfigureRoomFlowNode @AssistedInject constructor(
private val component by lazy {
parent!!.bindings<CreateRoomComponent.ParentBindings>().createRoomComponentBuilder().build()
}
private val navigator = plugins<CreateRoomNavigator>().first()

override val daggerComponent: Any
get() = component
Expand All @@ -69,8 +71,7 @@ class ConfigureRoomFlowNode @AssistedInject constructor(
createNode<AddPeopleNode>(buildContext = buildContext, plugins = listOf(callback))
}
NavTarget.ConfigureRoom -> {
val callbacks = plugins<ConfigureRoomNode.Callback>()
createNode<ConfigureRoomNode>(buildContext = buildContext, plugins = callbacks)
createNode<ConfigureRoomNode>(buildContext = buildContext, plugins = listOf(navigator))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,28 @@
package io.element.android.features.createroom.impl

import android.os.Parcelable
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.navigation.transition.JumpToEndTransitionHandler
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 dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.createroom.DefaultCreateRoomNavigator
import io.element.android.features.createroom.api.CreateRoomEntryPoint
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
import io.element.android.features.createroom.impl.joinbyaddress.JoinRoomByAddressNode
import io.element.android.features.createroom.impl.root.CreateRoomRootNode
import io.element.android.libraries.architecture.BackstackView
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 kotlinx.parcelize.Parcelize

@ContributesNode(SessionScope::class)
Expand All @@ -47,35 +50,38 @@ class CreateRoomFlowNode @AssistedInject constructor(

@Parcelize
data object NewRoom : NavTarget

@Parcelize
data object JoinByAddress : NavTarget
}

private val navigator = DefaultCreateRoomNavigator(
backstack = backstack,
overlay = overlay,
openRoom = { roomIdOrAlias, viaServers ->
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onOpenRoom(roomIdOrAlias, viaServers) }
}
)

override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) {
NavTarget.Root -> {
val callback = object : CreateRoomRootNode.Callback {
override fun onCreateNewRoom() {
backstack.push(NavTarget.NewRoom)
}

override fun onStartChatSuccess(roomId: RoomId) {
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onSuccess(roomId) }
}
}
createNode<CreateRoomRootNode>(buildContext = buildContext, plugins = listOf(callback))
createNode<CreateRoomRootNode>(buildContext = buildContext, plugins = listOf(navigator))
}
NavTarget.NewRoom -> {
val callback = object : ConfigureRoomNode.Callback {
override fun onCreateRoomSuccess(roomId: RoomId) {
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onSuccess(roomId) }
}
}
createNode<ConfigureRoomFlowNode>(buildContext = buildContext, plugins = listOf(callback))
createNode<ConfigureRoomFlowNode>(buildContext = buildContext, plugins = listOf(navigator))
}
NavTarget.JoinByAddress -> {
createNode<JoinRoomByAddressNode>(buildContext = buildContext, plugins = listOf(navigator))
}
}
}

@Composable
override fun View(modifier: Modifier) {
BackstackView()
Box(modifier = modifier) {
BackstackView()
OverlayView(transitionHandler = remember { JumpToEndTransitionHandler() })
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.createroom.CreateRoomNavigator
import io.element.android.features.createroom.impl.di.CreateRoomScope
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.services.analytics.api.AnalyticsService

@ContributesNode(CreateRoomScope::class)
Expand All @@ -29,6 +30,8 @@ class ConfigureRoomNode @AssistedInject constructor(
private val presenter: ConfigureRoomPresenter,
private val analyticsService: AnalyticsService,
) : Node(buildContext, plugins = plugins) {
private val navigator = plugins<CreateRoomNavigator>().first()

init {
lifecycle.subscribe(
onResume = {
Expand All @@ -37,22 +40,16 @@ class ConfigureRoomNode @AssistedInject constructor(
)
}

interface Callback : Plugin {
fun onCreateRoomSuccess(roomId: RoomId)
}

private fun onCreateRoomSuccess(roomId: RoomId) {
plugins<Callback>().forEach { it.onCreateRoomSuccess(roomId) }
}

@Composable
override fun View(modifier: Modifier) {
val state = presenter.present()
ConfigureRoomView(
state = state,
modifier = modifier,
onBackClick = this::navigateUp,
onCreateRoomSuccess = this::onCreateRoomSuccess,
onCreateRoomSuccess = {
navigator.onOpenRoom(roomIdOrAlias = it.toRoomIdOrAlias(), serverNames = emptyList())
},
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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.features.createroom.impl.joinbyaddress

sealed interface JoinRoomByAddressEvents {
data object Dismiss : JoinRoomByAddressEvents
data object Continue : JoinRoomByAddressEvents
data class UpdateAddress(val address: String) : JoinRoomByAddressEvents
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.features.createroom.impl.joinbyaddress

import androidx.compose.runtime.Composable
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
import io.element.android.features.createroom.CreateRoomNavigator
import io.element.android.libraries.di.SessionScope

@ContributesNode(SessionScope::class)
class JoinRoomByAddressNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
presenterFactory: JoinRoomByAddressPresenter.Factory,
) : Node(buildContext, plugins = plugins) {
private val navigator = plugins<CreateRoomNavigator>().first()
private val presenter = presenterFactory.create(navigator)

@Composable
override fun View(modifier: Modifier) {
val state = presenter.present()
JoinRoomByAddressView(
state = state,
modifier = modifier
)
}
}
Loading
Loading