Hey folks, Happy New Year. :tada: I need some hel...
# decompose
k
Hey folks, Happy New Year. 🎉 I need some help. My app crashes when I open a screen(Show) that I opened before. If you look at the video, I click on What If, Open Rick and Morty, The Simpsons, and then Family Guy. When I click on The Simpsons, I get the crash. Any pointers?
Copy code
java.lang.IllegalStateException: Configurations must be unique
       at com.arkivanov.decompose.router.children.ChildrenNavigator.switch(ChildrenNavigator.kt:114)
       at com.arkivanov.decompose.router.children.ChildrenNavigator.navigate(ChildrenNavigator.kt:108)
       at com.arkivanov.decompose.router.children.ChildrenFactoryKt$children$eventObserver$1.invoke(ChildrenFactory.kt:177)
       at com.arkivanov.decompose.router.children.ChildrenFactoryKt$children$eventObserver$1.invoke(ChildrenFactory.kt:174)
       at com.arkivanov.decompose.Relay.drainLoop(Relay.kt:48)
       at com.arkivanov.decompose.Relay.accept(Relay.kt:29)
       at com.arkivanov.decompose.router.stack.DefaultStackNavigation.navigate(DefaultStackNavigation.kt:11)
       at com.arkivanov.decompose.router.stack.StackNavigatorExtKt.push(StackNavigatorExt.kt:20)
       at com.arkivanov.decompose.router.stack.StackNavigatorExtKt.push$default(StackNavigatorExt.kt:19)
1
a
You can't have the same (by equality) configuration twice in the stack.
k
Is there a way to add a “unique” identifier. Say an id or something? If not, how can I fix this? It's an edge case but it would be great not to crash.
a
You can either generate a unique id for your needs (e.g. uuid), or perhaps the following would work for your case:
navigate { (it + MyConfig(...)).asReversed().distinct().asReversed() }
I could add an extension for this case.
k
That would be great. 🙂 I’ll try out the suggestion above
a
Let me know how it works!
👍 1
d
as a suggestion instead of using navigation.push you can also use navigation.bringtofront to avoid configuration duplication
a
bringToFront only allows one configuration of the specified class in the stack. As far as I understand, in this case there are multiple - the same screen but with different arguments. I suggest the behaviour as follows: if the specified configuration (by equality) is already presented in the stack, then it's brought to front (to avoid deep stacks with the same screens, like A1-A2-A1-A2-A1-A2), otherwise it's just pushed on top.
d
ooh Alright thank you for the clarification Arkadii
👍 1
k
Hey @Arkadii Ivanov The suggestion worked. Thanks. blob smile
a
Awesome! I will think about adding it to the library.
👍 2
I've been thinking about the API for this use case, tried various options. The best I could come up with is as follows:
Copy code
/**
 * Pushes the provided [configuration] at the top of the stack, removing the [configuration] from the back stack, if any.
 *
 * This API works similar to [bringToFront], except it compares configurations by equality rather than by configuration class.
 * 
 * @param onComplete called when the navigation is finished (either synchronously or asynchronously).
 */
@ExperimentalDecomposeApi
fun <C : Any> StackNavigator<C>.pushToFront(
    configuration: C,
    onComplete: () -> Unit = {},
) {
    navigate(
        transformer = { stack -> stack - configuration + configuration },
        onComplete = { _, _ -> onComplete() },
    )
}
How do you find this API? I have also tried adding an argument to
bringToFront
instead of adding a brand new function. But I didn't like the usage - it's quite verbose. A dedicated function looks better.
👍 1
d
The Api functionality looks great Arkadii
k
Hey @Arkadii Ivanov, I agree. Having a dedicated function looks better. 😎 It's an edge case, but I appreciate making the effort to add it.
🙏 1
a
FYI,
pushToFront
is released in Decompose 3.0.0-alpha05.
🚀 1
❤️ 1
k
Sweet. I will check it out. Thanks.