-
Notifications
You must be signed in to change notification settings - Fork 187
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
Fix notification navigation #2780
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,6 @@ 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 com.bumble.appyx.navmodel.backstack.operation.singleTop | ||
import dagger.assisted.Assisted | ||
import dagger.assisted.AssistedInject | ||
import io.element.android.anvilannotations.ContributesNode | ||
|
@@ -60,6 +59,7 @@ import io.element.android.features.securebackup.api.SecureBackupEntryPoint | |
import io.element.android.libraries.architecture.BackstackView | ||
import io.element.android.libraries.architecture.BaseFlowNode | ||
import io.element.android.libraries.architecture.createNode | ||
import io.element.android.libraries.architecture.waitForNavTargetAttached | ||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher | ||
import io.element.android.libraries.di.AppScope | ||
import io.element.android.libraries.di.SessionScope | ||
|
@@ -345,11 +345,6 @@ class LoggedInFlowNode @AssistedInject constructor( | |
} | ||
NavTarget.Ftue -> { | ||
ftueEntryPoint.nodeBuilder(this, buildContext) | ||
.callback(object : FtueEntryPoint.Callback { | ||
override fun onFtueFlowFinished() { | ||
lifecycleScope.launch { attachRoomList() } | ||
} | ||
}) | ||
.build() | ||
} | ||
NavTarget.RoomDirectorySearch -> { | ||
|
@@ -368,32 +363,22 @@ class LoggedInFlowNode @AssistedInject constructor( | |
} | ||
} | ||
|
||
suspend fun attachRoomList() { | ||
if (!canShowRoomList()) return | ||
attachChild<Node> { | ||
backstack.singleTop(NavTarget.RoomList) | ||
} | ||
} | ||
|
||
suspend fun attachRoom(roomId: RoomId) { | ||
if (!canShowRoomList()) return | ||
waitForNavTargetAttached { navTarget -> | ||
navTarget is NavTarget.RoomList | ||
} | ||
attachChild<RoomFlowNode> { | ||
backstack.singleTop(NavTarget.RoomList) | ||
backstack.push(NavTarget.Room(roomId.toRoomIdOrAlias())) | ||
} | ||
} | ||
|
||
private fun canShowRoomList(): Boolean { | ||
return ftueService.state.value is FtueState.Complete | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By the way, after a cold boot, |
||
} | ||
|
||
@Composable | ||
override fun View(modifier: Modifier) { | ||
Box(modifier = modifier) { | ||
val lockScreenState by lockScreenStateService.lockState.collectAsState() | ||
val isFtueDisplayed by ftueService.state.collectAsState() | ||
val ftueState by ftueService.state.collectAsState() | ||
BackstackView() | ||
if (isFtueDisplayed is FtueState.Complete) { | ||
if (ftueState is FtueState.Complete) { | ||
PermanentChild(permanentNavModel = permanentNavModel, navTarget = NavTarget.LoggedInPermanent) | ||
} | ||
if (lockScreenState == LockScreenLockState.Locked) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Ensure the application open the room when a notification is clicked. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
import com.bumble.appyx.core.children.nodeOrNull | ||
import com.bumble.appyx.core.node.Node | ||
import com.bumble.appyx.core.node.ParentNode | ||
import kotlinx.coroutines.cancel | ||
import kotlinx.coroutines.launch | ||
import kotlinx.coroutines.suspendCancellableCoroutine | ||
import kotlin.coroutines.resume | ||
|
@@ -48,3 +49,23 @@ | |
continuation.cancel() | ||
} | ||
} | ||
|
||
/** | ||
* Wait for a child to be attached to the parent node, only using the NavTarget. | ||
*/ | ||
suspend inline fun <NavTarget : Any> ParentNode<NavTarget>.waitForNavTargetAttached(crossinline predicate: (NavTarget) -> Boolean) = | ||
suspendCancellableCoroutine { continuation -> | ||
lifecycleScope.launch { | ||
children.collect { childMap -> | ||
val node = childMap.entries | ||
.map { it.key.navTarget } | ||
.lastOrNull(predicate) | ||
Check warning on line 62 in libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/ParentNodeExt.kt
|
||
if (node != null && !continuation.isCompleted) { | ||
continuation.resume(Unit) | ||
cancel() | ||
Check warning on line 65 in libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/ParentNodeExt.kt
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think But I do not want to do it in that PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like this also happens in the original |
||
} | ||
} | ||
}.invokeOnCompletion { | ||
continuation.cancel() | ||
Check warning on line 69 in libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/ParentNodeExt.kt
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the user is in the middle of FTUE when they tap on the notification? Shouldn't we add some kind of timeout or additional check? Otherwise I think this function will be suspended until then and suddenly resumed and the user presented with the room, and if they tap on several notifications I think they all will be suspended and suddenly resumed at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mmh, I did not test the use case of tapping a notification (neither tapping on multiple ones) when a ftue screen is displayed, I will test it.
But if at the end the room is displayed, I think this is the expected behavior.
As I said in the description, if the user clicks on a room permalink from outside the app, the user may have to log in first and at the end will se the room, because this method is suspending.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO that behaviour is bit weird, what if:
What will happen then? Will the 1st room be opened, the 2nd one, or both one after the other?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I just checked and all the rooms will be added to the backstack, and several back press will be necessary to go back to the room list. I think this is OK since:
We could ensure that the same room is not added twice on the backstack (i.e. click on a first notification, then get another one for the same room and click on this new one), but really this is edge cases, and this can be handled later if this is a reported issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should handle it here since we have the chance now, but if it's blocking some other PR I can approve it as is and we can handle it later.