Skip to content

Commit efb5acc

Browse files
authored
Merge pull request #4302 from element-hq/feature/fga/join_room_by_alias
Feature : join room by address
2 parents 1a7a8a8 + f00337e commit efb5acc

File tree

58 files changed

+880
-122
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+880
-122
lines changed

appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,8 @@ class LoggedInFlowNode @AssistedInject constructor(
357357
}
358358
NavTarget.CreateRoom -> {
359359
val callback = object : CreateRoomEntryPoint.Callback {
360-
override fun onSuccess(roomId: RoomId) {
361-
backstack.replace(NavTarget.Room(roomId.toRoomIdOrAlias()))
360+
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) {
361+
backstack.replace(NavTarget.Room(roomIdOrAlias = roomIdOrAlias, serverNames = serverNames))
362362
}
363363
}
364364

features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import com.bumble.appyx.core.modality.BuildContext
1111
import com.bumble.appyx.core.node.Node
1212
import com.bumble.appyx.core.plugin.Plugin
1313
import io.element.android.libraries.architecture.FeatureEntryPoint
14-
import io.element.android.libraries.matrix.api.core.RoomId
14+
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
1515

1616
interface CreateRoomEntryPoint : FeatureEntryPoint {
1717
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
@@ -21,6 +21,6 @@ interface CreateRoomEntryPoint : FeatureEntryPoint {
2121
}
2222

2323
interface Callback : Plugin {
24-
fun onSuccess(roomId: RoomId)
24+
fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>)
2525
}
2626
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.features.createroom
9+
10+
import com.bumble.appyx.core.plugin.Plugin
11+
import com.bumble.appyx.navmodel.backstack.BackStack
12+
import com.bumble.appyx.navmodel.backstack.operation.push
13+
import io.element.android.features.createroom.impl.CreateRoomFlowNode.NavTarget
14+
import io.element.android.libraries.architecture.overlay.Overlay
15+
import io.element.android.libraries.architecture.overlay.operation.hide
16+
import io.element.android.libraries.architecture.overlay.operation.show
17+
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
18+
19+
interface CreateRoomNavigator : Plugin {
20+
fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>)
21+
fun onCreateNewRoom()
22+
fun onShowJoinRoomByAddress()
23+
fun onDismissJoinRoomByAddress()
24+
}
25+
26+
class DefaultCreateRoomNavigator(
27+
private val backstack: BackStack<NavTarget>,
28+
private val overlay: Overlay<NavTarget>,
29+
private val openRoom: (RoomIdOrAlias, List<String>) -> Unit,
30+
) : CreateRoomNavigator {
31+
override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>) = openRoom(roomIdOrAlias, serverNames)
32+
33+
override fun onCreateNewRoom() {
34+
backstack.push(NavTarget.NewRoom)
35+
}
36+
37+
override fun onShowJoinRoomByAddress() {
38+
overlay.show(NavTarget.JoinByAddress)
39+
}
40+
41+
override fun onDismissJoinRoomByAddress() {
42+
overlay.hide()
43+
}
44+
}

features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/ConfigureRoomFlowNode.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push
1919
import dagger.assisted.Assisted
2020
import dagger.assisted.AssistedInject
2121
import io.element.android.anvilannotations.ContributesNode
22+
import io.element.android.features.createroom.CreateRoomNavigator
2223
import io.element.android.features.createroom.impl.addpeople.AddPeopleNode
2324
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
2425
import io.element.android.features.createroom.impl.di.CreateRoomComponent
@@ -46,6 +47,7 @@ class ConfigureRoomFlowNode @AssistedInject constructor(
4647
private val component by lazy {
4748
parent!!.bindings<CreateRoomComponent.ParentBindings>().createRoomComponentBuilder().build()
4849
}
50+
private val navigator = plugins<CreateRoomNavigator>().first()
4951

5052
override val daggerComponent: Any
5153
get() = component
@@ -69,8 +71,7 @@ class ConfigureRoomFlowNode @AssistedInject constructor(
6971
createNode<AddPeopleNode>(buildContext = buildContext, plugins = listOf(callback))
7072
}
7173
NavTarget.ConfigureRoom -> {
72-
val callbacks = plugins<ConfigureRoomNode.Callback>()
73-
createNode<ConfigureRoomNode>(buildContext = buildContext, plugins = callbacks)
74+
createNode<ConfigureRoomNode>(buildContext = buildContext, plugins = listOf(navigator))
7475
}
7576
}
7677
}

features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt

+26-20
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,28 @@
88
package io.element.android.features.createroom.impl
99

1010
import android.os.Parcelable
11+
import androidx.compose.foundation.layout.Box
1112
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.remember
1214
import androidx.compose.ui.Modifier
1315
import com.bumble.appyx.core.modality.BuildContext
16+
import com.bumble.appyx.core.navigation.transition.JumpToEndTransitionHandler
1417
import com.bumble.appyx.core.node.Node
1518
import com.bumble.appyx.core.plugin.Plugin
1619
import com.bumble.appyx.core.plugin.plugins
1720
import com.bumble.appyx.navmodel.backstack.BackStack
18-
import com.bumble.appyx.navmodel.backstack.operation.push
1921
import dagger.assisted.Assisted
2022
import dagger.assisted.AssistedInject
2123
import io.element.android.anvilannotations.ContributesNode
24+
import io.element.android.features.createroom.DefaultCreateRoomNavigator
2225
import io.element.android.features.createroom.api.CreateRoomEntryPoint
23-
import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode
26+
import io.element.android.features.createroom.impl.joinbyaddress.JoinRoomByAddressNode
2427
import io.element.android.features.createroom.impl.root.CreateRoomRootNode
2528
import io.element.android.libraries.architecture.BackstackView
2629
import io.element.android.libraries.architecture.BaseFlowNode
30+
import io.element.android.libraries.architecture.OverlayView
2731
import io.element.android.libraries.architecture.createNode
2832
import io.element.android.libraries.di.SessionScope
29-
import io.element.android.libraries.matrix.api.core.RoomId
3033
import kotlinx.parcelize.Parcelize
3134

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

4851
@Parcelize
4952
data object NewRoom : NavTarget
53+
54+
@Parcelize
55+
data object JoinByAddress : NavTarget
5056
}
5157

58+
private val navigator = DefaultCreateRoomNavigator(
59+
backstack = backstack,
60+
overlay = overlay,
61+
openRoom = { roomIdOrAlias, viaServers ->
62+
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onOpenRoom(roomIdOrAlias, viaServers) }
63+
}
64+
)
65+
5266
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
5367
return when (navTarget) {
5468
NavTarget.Root -> {
55-
val callback = object : CreateRoomRootNode.Callback {
56-
override fun onCreateNewRoom() {
57-
backstack.push(NavTarget.NewRoom)
58-
}
59-
60-
override fun onStartChatSuccess(roomId: RoomId) {
61-
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onSuccess(roomId) }
62-
}
63-
}
64-
createNode<CreateRoomRootNode>(buildContext = buildContext, plugins = listOf(callback))
69+
createNode<CreateRoomRootNode>(buildContext = buildContext, plugins = listOf(navigator))
6570
}
6671
NavTarget.NewRoom -> {
67-
val callback = object : ConfigureRoomNode.Callback {
68-
override fun onCreateRoomSuccess(roomId: RoomId) {
69-
plugins<CreateRoomEntryPoint.Callback>().forEach { it.onSuccess(roomId) }
70-
}
71-
}
72-
createNode<ConfigureRoomFlowNode>(buildContext = buildContext, plugins = listOf(callback))
72+
createNode<ConfigureRoomFlowNode>(buildContext = buildContext, plugins = listOf(navigator))
73+
}
74+
NavTarget.JoinByAddress -> {
75+
createNode<JoinRoomByAddressNode>(buildContext = buildContext, plugins = listOf(navigator))
7376
}
7477
}
7578
}
7679

7780
@Composable
7881
override fun View(modifier: Modifier) {
79-
BackstackView()
82+
Box(modifier = modifier) {
83+
BackstackView()
84+
OverlayView(transitionHandler = remember { JumpToEndTransitionHandler() })
85+
}
8086
}
8187
}

features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomNode.kt

+7-10
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ import dagger.assisted.Assisted
1818
import dagger.assisted.AssistedInject
1919
import im.vector.app.features.analytics.plan.MobileScreen
2020
import io.element.android.anvilannotations.ContributesNode
21+
import io.element.android.features.createroom.CreateRoomNavigator
2122
import io.element.android.features.createroom.impl.di.CreateRoomScope
22-
import io.element.android.libraries.matrix.api.core.RoomId
23+
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
2324
import io.element.android.services.analytics.api.AnalyticsService
2425

2526
@ContributesNode(CreateRoomScope::class)
@@ -29,6 +30,8 @@ class ConfigureRoomNode @AssistedInject constructor(
2930
private val presenter: ConfigureRoomPresenter,
3031
private val analyticsService: AnalyticsService,
3132
) : Node(buildContext, plugins = plugins) {
33+
private val navigator = plugins<CreateRoomNavigator>().first()
34+
3235
init {
3336
lifecycle.subscribe(
3437
onResume = {
@@ -37,22 +40,16 @@ class ConfigureRoomNode @AssistedInject constructor(
3740
)
3841
}
3942

40-
interface Callback : Plugin {
41-
fun onCreateRoomSuccess(roomId: RoomId)
42-
}
43-
44-
private fun onCreateRoomSuccess(roomId: RoomId) {
45-
plugins<Callback>().forEach { it.onCreateRoomSuccess(roomId) }
46-
}
47-
4843
@Composable
4944
override fun View(modifier: Modifier) {
5045
val state = presenter.present()
5146
ConfigureRoomView(
5247
state = state,
5348
modifier = modifier,
5449
onBackClick = this::navigateUp,
55-
onCreateRoomSuccess = this::onCreateRoomSuccess,
50+
onCreateRoomSuccess = {
51+
navigator.onOpenRoom(roomIdOrAlias = it.toRoomIdOrAlias(), serverNames = emptyList())
52+
},
5653
)
5754
}
5855
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.features.createroom.impl.joinbyaddress
9+
10+
sealed interface JoinRoomByAddressEvents {
11+
data object Dismiss : JoinRoomByAddressEvents
12+
data object Continue : JoinRoomByAddressEvents
13+
data class UpdateAddress(val address: String) : JoinRoomByAddressEvents
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.features.createroom.impl.joinbyaddress
9+
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.ui.Modifier
12+
import com.bumble.appyx.core.modality.BuildContext
13+
import com.bumble.appyx.core.node.Node
14+
import com.bumble.appyx.core.plugin.Plugin
15+
import com.bumble.appyx.core.plugin.plugins
16+
import dagger.assisted.Assisted
17+
import dagger.assisted.AssistedInject
18+
import io.element.android.anvilannotations.ContributesNode
19+
import io.element.android.features.createroom.CreateRoomNavigator
20+
import io.element.android.libraries.di.SessionScope
21+
22+
@ContributesNode(SessionScope::class)
23+
class JoinRoomByAddressNode @AssistedInject constructor(
24+
@Assisted buildContext: BuildContext,
25+
@Assisted plugins: List<Plugin>,
26+
presenterFactory: JoinRoomByAddressPresenter.Factory,
27+
) : Node(buildContext, plugins = plugins) {
28+
private val navigator = plugins<CreateRoomNavigator>().first()
29+
private val presenter = presenterFactory.create(navigator)
30+
31+
@Composable
32+
override fun View(modifier: Modifier) {
33+
val state = presenter.present()
34+
JoinRoomByAddressView(
35+
state = state,
36+
modifier = modifier
37+
)
38+
}
39+
}

0 commit comments

Comments
 (0)