Skip to content

Commit 682fd45

Browse files
authored
Merge pull request #2780 from element-hq/feature/bma/fixNotificationNavigation
Fix notification navigation
2 parents 82621d9 + f807d57 commit 682fd45

File tree

7 files changed

+30
-37
lines changed

7 files changed

+30
-37
lines changed

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

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import com.bumble.appyx.core.plugin.plugins
3535
import com.bumble.appyx.navmodel.backstack.BackStack
3636
import com.bumble.appyx.navmodel.backstack.operation.push
3737
import com.bumble.appyx.navmodel.backstack.operation.replace
38-
import com.bumble.appyx.navmodel.backstack.operation.singleTop
3938
import dagger.assisted.Assisted
4039
import dagger.assisted.AssistedInject
4140
import io.element.android.anvilannotations.ContributesNode
@@ -60,6 +59,7 @@ import io.element.android.features.securebackup.api.SecureBackupEntryPoint
6059
import io.element.android.libraries.architecture.BackstackView
6160
import io.element.android.libraries.architecture.BaseFlowNode
6261
import io.element.android.libraries.architecture.createNode
62+
import io.element.android.libraries.architecture.waitForNavTargetAttached
6363
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
6464
import io.element.android.libraries.di.AppScope
6565
import io.element.android.libraries.di.SessionScope
@@ -345,11 +345,6 @@ class LoggedInFlowNode @AssistedInject constructor(
345345
}
346346
NavTarget.Ftue -> {
347347
ftueEntryPoint.nodeBuilder(this, buildContext)
348-
.callback(object : FtueEntryPoint.Callback {
349-
override fun onFtueFlowFinished() {
350-
lifecycleScope.launch { attachRoomList() }
351-
}
352-
})
353348
.build()
354349
}
355350
NavTarget.RoomDirectorySearch -> {
@@ -368,32 +363,22 @@ class LoggedInFlowNode @AssistedInject constructor(
368363
}
369364
}
370365

371-
suspend fun attachRoomList() {
372-
if (!canShowRoomList()) return
373-
attachChild<Node> {
374-
backstack.singleTop(NavTarget.RoomList)
375-
}
376-
}
377-
378366
suspend fun attachRoom(roomId: RoomId) {
379-
if (!canShowRoomList()) return
367+
waitForNavTargetAttached { navTarget ->
368+
navTarget is NavTarget.RoomList
369+
}
380370
attachChild<RoomFlowNode> {
381-
backstack.singleTop(NavTarget.RoomList)
382371
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias()))
383372
}
384373
}
385374

386-
private fun canShowRoomList(): Boolean {
387-
return ftueService.state.value is FtueState.Complete
388-
}
389-
390375
@Composable
391376
override fun View(modifier: Modifier) {
392377
Box(modifier = modifier) {
393378
val lockScreenState by lockScreenStateService.lockState.collectAsState()
394-
val isFtueDisplayed by ftueService.state.collectAsState()
379+
val ftueState by ftueService.state.collectAsState()
395380
BackstackView()
396-
if (isFtueDisplayed is FtueState.Complete) {
381+
if (ftueState is FtueState.Complete) {
397382
PermanentChild(permanentNavModel = permanentNavModel, navTarget = NavTarget.LoggedInPermanent)
398383
}
399384
if (lockScreenState == LockScreenLockState.Locked) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ class RootFlowNode @AssistedInject constructor(
288288
.attachSession()
289289
.apply {
290290
when (deeplinkData) {
291-
is DeeplinkData.Root -> attachRoomList()
291+
is DeeplinkData.Root -> Unit // The room list will always be shown, observing FtueState
292292
is DeeplinkData.Room -> attachRoom(deeplinkData.roomId)
293293
}
294294
}

changelog.d/2778.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Ensure the application open the room when a notification is clicked.

features/ftue/api/src/main/kotlin/io/element/android/features/ftue/api/FtueEntryPoint.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,12 @@ package io.element.android.features.ftue.api
1818

1919
import com.bumble.appyx.core.modality.BuildContext
2020
import com.bumble.appyx.core.node.Node
21-
import com.bumble.appyx.core.plugin.Plugin
2221
import io.element.android.libraries.architecture.FeatureEntryPoint
2322

2423
interface FtueEntryPoint : FeatureEntryPoint {
2524
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
2625

2726
interface NodeBuilder {
28-
fun callback(callback: Callback): NodeBuilder
2927
fun build(): Node
3028
}
31-
32-
interface Callback : Plugin {
33-
fun onFtueFlowFinished()
34-
}
3529
}

features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPoint.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@ class DefaultFtueEntryPoint @Inject constructor() : FtueEntryPoint {
3131
val plugins = ArrayList<Plugin>()
3232

3333
return object : FtueEntryPoint.NodeBuilder {
34-
override fun callback(callback: FtueEntryPoint.Callback): FtueEntryPoint.NodeBuilder {
35-
plugins += callback
36-
return this
37-
}
38-
3934
override fun build(): Node {
4035
return parentNode.createNode<FtueFlowNode>(buildContext, plugins)
4136
}

features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import dagger.assisted.Assisted
3232
import dagger.assisted.AssistedInject
3333
import io.element.android.anvilannotations.ContributesNode
3434
import io.element.android.features.analytics.api.AnalyticsEntryPoint
35-
import io.element.android.features.ftue.api.FtueEntryPoint
3635
import io.element.android.features.ftue.impl.notifications.NotificationsOptInNode
3736
import io.element.android.features.ftue.impl.sessionverification.FtueSessionVerificationFlowNode
3837
import io.element.android.features.ftue.impl.state.DefaultFtueService
@@ -86,8 +85,6 @@ class FtueFlowNode @AssistedInject constructor(
8685
data object LockScreenSetup : NavTarget
8786
}
8887

89-
private val callback = plugins.filterIsInstance<FtueEntryPoint.Callback>().firstOrNull()
90-
9188
override fun onBuilt() {
9289
super.onBuilt()
9390

@@ -157,7 +154,7 @@ class FtueFlowNode @AssistedInject constructor(
157154
FtueStep.LockscreenSetup -> {
158155
backstack.newRoot(NavTarget.LockScreenSetup)
159156
}
160-
null -> callback?.onFtueFlowFinished()
157+
null -> Unit
161158
}
162159
}
163160

libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/ParentNodeExt.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import androidx.lifecycle.lifecycleScope
2020
import com.bumble.appyx.core.children.nodeOrNull
2121
import com.bumble.appyx.core.node.Node
2222
import com.bumble.appyx.core.node.ParentNode
23+
import kotlinx.coroutines.cancel
2324
import kotlinx.coroutines.launch
2425
import kotlinx.coroutines.suspendCancellableCoroutine
2526
import kotlin.coroutines.resume
@@ -48,3 +49,23 @@ suspend inline fun <reified N : Node, NavTarget : Any> ParentNode<NavTarget>.wai
4849
continuation.cancel()
4950
}
5051
}
52+
53+
/**
54+
* Wait for a child to be attached to the parent node, only using the NavTarget.
55+
*/
56+
suspend inline fun <NavTarget : Any> ParentNode<NavTarget>.waitForNavTargetAttached(crossinline predicate: (NavTarget) -> Boolean) =
57+
suspendCancellableCoroutine { continuation ->
58+
lifecycleScope.launch {
59+
children.collect { childMap ->
60+
val node = childMap.entries
61+
.map { it.key.navTarget }
62+
.lastOrNull(predicate)
63+
if (node != null && !continuation.isCompleted) {
64+
continuation.resume(Unit)
65+
cancel()
66+
}
67+
}
68+
}.invokeOnCompletion {
69+
continuation.cancel()
70+
}
71+
}

0 commit comments

Comments
 (0)