Giter Site home page Giter Site logo

badoo / decompose Goto Github PK

View Code? Open in Web Editor NEW
817.0 25.0 41.0 65.76 MB

Kotlin Multiplatform lifecycle-aware business logic components (aka BLoCs) with routing functionality and pluggable UI (Jetpack Compose, SwiftUI, JS React, etc.), inspired by Badoos RIBs fork of the Uber RIBs framework

Home Page: https://arkivanov.github.io/Decompose

License: Apache License 2.0

Kotlin 100.00%
android jetpack-compose components kotlin tree-structure multiplatform lifecycle lifecycle-aware-components hacktoberfest

decompose's People

Contributors

arkivanov avatar jimkarsh avatar maxtox3 avatar moffpage avatar morfly avatar nikola-milovic avatar plusmobileapps avatar steelahhh avatar theapache64 avatar vkazanov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

decompose's Issues

Unit tests and testing library

Are there any plans or ideas of having a testing library to create something like an integration test of navigations in common code?

With regards to tests, are writing tests for the project planned anytime soon? I'll be glad to contribute in writing them.

Decompose API in iOS framework

Decompose API that are not used in the shared module is not exported to the iOS framework. For example when MutableValue is not exposed through a public interface it won't be exported in the framework therefore you can't use it in iOS code.

Maybe I am missing a configuration? I'm not sure. I'm thinking on top of my head that maybe a cocoapods is needed to directly access its APIs?

Error: java.lang.NoClassDefFoundError: android/os/Looper in: DefaultStore.kt:31

Caused by: java.lang.NoClassDefFoundError: android/os/Looper
at kotlinx.coroutines.android.AndroidDispatcherFactory.createDispatcher(HandlerDispatcher.kt:55)
at kotlinx.coroutines.android.AndroidDispatcherFactory.createDispatcher(HandlerDispatcher.kt:52)
at kotlinx.coroutines.internal.MainDispatchersKt.tryCreateDispatcher(MainDispatchers.kt:57)
at kotlinx.coroutines.internal.MainDispatcherLoader.loadMainDispatcher(MainDispatchers.kt:38)
at kotlinx.coroutines.internal.MainDispatcherLoader.(MainDispatchers.kt:22)
at kotlinx.coroutines.Dispatchers.getMain(Dispatchers.kt:58)
at com.arkivanov.mvikotlin.extensions.coroutines.SuspendExecutor.(SuspendExecutor.kt:23)
at com.shabinder.common.main.store.SpotiFlyerMainStoreProvider$ExecutorImpl.(SpotiFlyerMainStoreProvider.kt:57)
at com.shabinder.common.main.store.SpotiFlyerMainStoreProvider$provide$1$1.invoke(SpotiFlyerMainStoreProvider.kt)
at com.shabinder.common.main.store.SpotiFlyerMainStoreProvider$provide$1$1.invoke(SpotiFlyerMainStoreProvider.kt)
at com.arkivanov.mvikotlin.main.store.DefaultStore.(DefaultStore.kt:31)
... 143 more

image

My Store Creator:
image

My Suspend Executor:
image

All methods like openPlatform,etc are just expect/actual empty blocks
image

"Used by" list

It would be good to have a list of companies/users/projects where Decompose is used. I suggest to stick to the following format, but feel free to omit/add/modify any details:

Project name: [project name]
Project type: production/pet/sample
Company name: personal/[company name]
Supported targets: android, jvm, js, iosX64, iosArm64, macosX64, linuxX64
Sources link (if open source): [link]

Can not resolve jetbrains compose extension in your bintray

repositories {
    maven { url = uri("https://dl.bintray.com/arkivanov/maven") }
}
dependencies {
    
    val decomposeVersion = "0.1.2"
    implementation("com.arkivanov.decompose:decompose:$decomposeVersion")
    implementation("com.arkivanov.decompose:extension-compose-jetbrains:$decomposeVersion")

}

Error:

Execution failed for task ':compileKotlin'.
> Could not resolve all files for configuration ':compileClasspath'.
   > Could not find com.arkivanov.decompose:extension-compose-jetbrains:0.1.2

Adding Decompose into the Jetbrains KMM/Compose template

I started a project with the default template crated by IDEA for a KMM Compose project:
image

Now I'm trying to add Decompse in, and it is having some issues.

I added the dependency to common/build.gradle.kts as such:

    ...
    sourceSets {
        val commonMain by getting {
            dependencies {
                api(compose.runtime)
                api(compose.foundation)
                api(compose.material)
                api(compose.ui)

                implementation("com.arkivanov.decompose:decompose:0.1.8")
                implementation("com.arkivanov.decompose:extensions-compose-jetbrains:0.1.8")
            }
        }
...

However in source files inside commonMain the IDE doesn't know about the classes. I can add them via manual import, but still, that seems like a problem, has anyone else encountered this?

Describe in the documentation how one can extend ComponentContext

Users are asking questions about how one can extend ComponentContext with additional app-wide things. I came up with a solution. Would be nice do add this as a suggestion to the docs. If somebody thinks this can be improved, please let me know.

interface AppComponentContext : ComponentContext {

    // Custom things here
}

class DefaultAppComponentContext(
    componentContext: ComponentContext,
    // Additional dependencies here
) : AppComponentContext, ComponentContext by componentContext {

    // Custom things implementation here
}

fun <C : Parcelable, T : Any> AppComponentContext.appRouter(
    initialConfiguration: () -> C,
    initialBackStack: () -> List<C> = ::emptyList,
    configurationClass: KClass<out C>,
    key: String = "DefaultRouter",
    handleBackButton: Boolean = false,
    componentFactory: (configuration: C, AppComponentContext) -> T
): Router<C, T> =
    router(
        initialConfiguration = initialConfiguration,
        initialBackStack = initialBackStack,
        configurationClass = configurationClass,
        key = key,
        handleBackButton = handleBackButton
    ) { configuration, componentContext ->
        componentFactory(
            configuration,
            DefaultAppComponentContext(
                componentContext = componentContext
            )
        )
    }

class MyComponent(componentContext: AppComponentContext): AppComponentContext by componentContext {
    
    // Use AppComponentContext here
}

Add Children function overloads with RouterState argument

There is Children function in extensions-compose-jetpack and extensions-compose-jetbrains modules:

@Composable
fun <C : Any, T : Any> Children(
    routerState: Value<RouterState<C, T>>,
    animation: ChildAnimation<C, T> = { state, childContent -> childContent(state.activeChild) },
    content: ChildContent<C, T>
) { ... }

We also need the following variant:

@Composable
fun <C : Any, T : Any> Children(
    routerState: RouterState<C, T>,
    animation: ChildAnimation<C, T> = { state, childContent -> childContent(state.activeChild) },
    content: ChildContent<C, T>
) { ... }

The former should just call the latter.

Suspend function usage in ViewModels

I have setup a viewmodel in common kmm module, binded with decompose instance keeper, that run suspend function in the init phase of the class instantiation.

I does work fine in Android

But in iOS I get such error at runtime, when I instantiate the ViewModel and I define @ObservedObject from ObserveValue.

struct RootView: View {
    // DEPENDENCY
    private let viewModel: PocFeatureViewModel

    // STATE
    @State var brightness: Double = 5

    @ObservedObject private var viewState: ObservableValue<LightViewState>
    
    @ObservedObject private var status: ObservableValue<NSString>
    
    // LIFE CYCLE
    init(_ viewModel: PocFeatureViewModel) {
        self.viewModel = viewModel
        self.viewState = ObservableValue(viewModel.viewState)
        self.status = ObservableValue(viewModel.status)
    }
    
    var body: some View {
   // ...
    }
}

Here is the trace. Any idea ?

Function doesn't have or inherit @throws annotation and thus exception isn't propagated from Kotlin to Objective-C/Swift as NSError.
It is considered unexpected and unhandled instead. Program will be terminated.
Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen com.arkivanov.decompose.value.MutableValueImpl@1ad5008
Uncaught Kotlin exception: kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[WorkerCoroutineDispatcherImpl@1419118, Continuation @ $start$lambda-0COROUTINE$0]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers

Missing `lifecycle` parameter for `observe` function (jetbrains-compose.v020-build128)

This is the decompose setup I use (following the guide in the readme):

import androidx.compose.foundation.layout.Column
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import com.arkivanov.decompose.value.MutableValue
import com.arkivanov.decompose.value.Value
import com.arkivanov.decompose.value.observe

class WithCharacterState {
    private val _value = MutableValue(mutableListOf<Character>())
    val state: Value<List<Character>> = _value

    fun addCharacter(character: Character) {
        _value.value.add(character)
    }
}

@Composable
fun WithCharacterState.render() {
    state.observe { state ->
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Text(text = state.toString())

            Button(onClick = { addCharacter(CharacterTemplate.DEFAULT_CHARACTER)} ) {
                Text("Add Character")
            }
        }
    }
}

However I receive the following two errors:

e: /xetra11/app/module/character/WithCharacterState.kt: (25, 11): No value passed for parameter 'lifecycle'
e: /xetra11/app/module/character/WithCharacterState.kt: (26, 9): @Composable invocations can only happen from the context of a @Composable function

my build.gradle.kts:

import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.4.20"
    id("org.jetbrains.compose") version "0.2.0-build128"
}

group = "com.github.xetra11"
version = "0.0.1"

repositories {
    jcenter()
    mavenCentral()
    google()
    maven { url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev") }
    maven { url = uri("https://dl.bintray.com/arkivanov/maven") }
}

dependencies {
    implementation(compose.desktop.currentOs)
    implementation("org.slf4j:slf4j-simple:2.0.0-alpha1")

    val decomposeVersion = "0.1.2"
    implementation("com.arkivanov.decompose:decompose:$decomposeVersion")
    implementation("com.arkivanov.decompose:extensions-compose-jetbrains:$decomposeVersion")

    testImplementation(kotlin("test-junit5"))
    testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
    testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
    testImplementation("org.assertj:assertj-core:3.18.1")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile>() {
    kotlinOptions.jvmTarget = "11"
}

compose.desktop {
    application {
        mainClass = "MainKt"
        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "app"
        }
    }
}

Router.pop throwing Exception

When I call router.pop within a few milliseconds of pushing a child, An exception is thrown with the following Message:
"Configuration stack can not be empty"

Am I doing something wrong, but if I call router.pop say after a delay of 200ms, it works as expected

Any plan for test?

I think current there is not a simle way to test a class implementation ComponentContext (for example, how to provide ComponentContext)

Decompose 0.2.3 crushing with compose ver 1.0.0-beta04+

Crushlog E/AndroidRuntime: FATAL EXCEPTION: main Process: cam.ishare.android.app, PID: 8224 java.lang.NoSuchFieldError: No static field Companion of type Landroidx/compose/foundation/layout/BoxScope$Companion; in class Landroidx/compose/foundation/layout/BoxScope; or its superclasses (declaration of 'androidx.compose.foundation.layout.BoxScope' appears in /data/app/cam.ishare.android.app-x68C3yGqeDzPFGtS48KUzA==/base.apk) at com.arkivanov.decompose.extensions.compose.jetpack.animation.page.PageAnimationKt$PageAnimationFrame$1$1$1.invoke(PageAnimation.kt:197) at com.arkivanov.decompose.extensions.compose.jetpack.animation.page.PageAnimationKt$PageAnimationFrame$1$1$1.invoke(PageAnimation.kt:141) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at com.arkivanov.decompose.extensions.compose.jetpack.animation.child.CrossfadeScaleKt$crossfadeScale$1.invoke(CrossfadeScale.kt:22) at com.arkivanov.decompose.extensions.compose.jetpack.animation.child.CrossfadeScaleKt$crossfadeScale$1.invoke(CrossfadeScale.kt:21) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:254) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at com.arkivanov.decompose.extensions.compose.jetpack.animation.page.PageAnimationKt$PageAnimationFrame$1.invoke(PageAnimation.kt:141) at com.arkivanov.decompose.extensions.compose.jetpack.animation.page.PageAnimationKt$PageAnimationFrame$1.invoke(PageAnimation.kt:132) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1.invoke(BoxWithConstraints.kt:61) at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1.invoke(BoxWithConstraints.kt:61) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1.invoke(SubcomposeLayout.kt:167) at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1.invoke(SubcomposeLayout.kt:167) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34) at androidx.compose.runtime.ComposerKt.invokeComposable(Composer.kt:3235) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2514) at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:2478) at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:453) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:702) at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:2914) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:409) at androidx.compose.ui.layout.SubcomposeLayoutState.subcomposeInto(SubcomposeLayout.kt:184) at androidx.compose.ui.layout.SubcomposeLayoutState.access$subcomposeInto(SubcomposeLayout.kt:100) at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:160) at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:158) at androidx.compose.runtime.snapshots.SnapshotStateObserver.withNoObservations(SnapshotStateObserver.kt:137) at androidx.compose.ui.node.OwnerSnapshotObserver.withNoSnapshotReadObservation$ui_release(OwnerSnapshotObserver.kt:49) at androidx.compose.ui.node.LayoutNode.withNoSnapshotReadObservation$ui_release(LayoutNode.kt:1054) E/AndroidRuntime: at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:158) at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:152) at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke-0kLqBqw(BoxWithConstraints.kt:61) at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke(BoxWithConstraints.kt:59) at androidx.compose.ui.layout.SubcomposeLayoutState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:212) at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45) at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95) at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:121) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:75) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:63) at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94) at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:68) at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1172) at androidx.compose.foundation.layout.RowColumnImplKt$rowColumnMeasurePolicy$1.measure-3p2s80s(RowColumnImpl.kt:89) at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45) at androidx.compose.foundation.layout.FillModifier.measure-3p2s80s(Size.kt:650) at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:37) at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95) at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:121) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:75) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:63) at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94) at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:68) at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1172) at androidx.compose.foundation.layout.BoxKt$boxMeasurePolicy$1.measure-3p2s80s(Box.kt:111) at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45) at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:213) at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:37) at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108) at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:213) at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:37) at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95) at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:121) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:75) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:63) at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94) E/AndroidRuntime: at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:68) at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1172) at androidx.compose.ui.layout.RootMeasurePolicy.measure-3p2s80s(RootMeasurePolicy.kt:38) at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45) at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108) at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108) at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108) at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108) at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95) at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:1787) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:116) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:75) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:63) at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94) at androidx.compose.ui.node.LayoutNode.remeasure-BRTryo0$ui_release(LayoutNode.kt:1179) at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-0kLqBqw(MeasureAndLayoutDelegate.kt:170) at androidx.compose.ui.node.MeasureAndLayoutDelegate.access$doRemeasure-0kLqBqw(MeasureAndLayoutDelegate.kt:39) at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:212) at androidx.compose.ui.platform.AndroidComposeView.onMeasure(AndroidComposeView.android.kt:543) at android.view.View.measure(View.java:23169) at androidx.compose.ui.platform.AbstractComposeView.onMeasure(ComposeView.android.kt:249) at android.view.View.measure(View.java:23169) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:23169) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535) at android.widget.LinearLayout.measureVertical(LinearLayout.java:825) at android.widget.LinearLayout.onMeasure(LinearLayout.java:704) at android.view.View.measure(View.java:23169) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at com.android.internal.policy.DecorView.onMeasure(DecorView.java:716) at android.view.View.measure(View.java:23169) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2718) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1572) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1855) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1460) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949) at android.view.Choreographer.doCallbacks(Choreographer.java:761) at android.view.Choreographer.doFrame(Choreographer.java:696) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) I/Process: Sending signal. PID: 8224 SIG: 9

InstanceKeeper is not destroyed at the end of lifecycle when not passed to ComponentContext

In non-android targets it does not make sense to use InstanceKeeper, and so there is no need to pass it to DefaultComponentContext. When InstanceKeeper is not passed to DefaultComponentContext, it is created implicitly. This allows using InstanceKeeper in common code.

The bug: when InstanceKeeper is not passed to DefaultComponentContext, it is not destroyed at the end of lifecycle.
Temporary workaround: create InstanceKeeper manually using DefaultInstanceKeeper builder function, pass it to DefaultComponentContext, destroy it manually at the end of lifcycle.

Add watchOS support

  • Apple watchOS on ARM64 (Apple Watch Series 4 and newer)
  • ARM32 (earlier models) platforms
  • desktop simulators

Publish sources for Android modules

Sources are not published for the following Android-only modules: extensions-android and extensions-compose-jetpack. We should add sources.jar to publications. This will allow us to enable synchronization with JCenter.

Tutorial section in docs

  • Transitions
  • Deeplinks
    - Internal and external links
  • Multiple routers based on responsive design
    - Mobile screen size: Navigating from the master screen to the detail screen.
    - Larger screen size: master and detail screens are visible at the same time, selecting one item in the master screen changes the content of the detail screen.
    - Sample: Gmail app in mobile vs tablet (But thinking that this should be possible to do resizing a desktop
    screen, without losing the selected item, scroll position, etc).

Dependency Updates Gradle Plugin fails to determine the version of Decompose

Dependency Updates Gradle Plugin (link: https://github.com/ben-manes/gradle-versions-plugin) fails to determine the version of Decompose even with explicit indication (I used the current recent 0.2.4) like this:

implementation(dependencyNotation = "com.arkivanov.decompose:decompose:0.2.4")
implementation(dependencyNotation = "com.arkivanov.decompose:extensions-compose-jetpack:0.2.4")

I just add this block:

plugins {
  id("com.github.ben-manes.versions") version "0.38.0"
}

inside root project's build.gradle.kts file and providing implementations how it should be done.

You can easily create the project by yourself, after all of that run gradle dependencyUpdates with --info optionally to get more details

NoSuchMethodError: No interface method startReplaceableGroup with Compose 1.0.0-beta07

Got this exception after trying to update Compose to 1.0.0-beta07

 java.lang.NoSuchMethodError: No interface method startReplaceableGroup(ILjava/lang/String;)V in class Landroidx/compose/runtime/Composer; or its super classes (declaration of 'androidx.compose.runtime.Composer' appears in /data/app/com.aglushkov.wordteacher.androidApp-4keQzDtu0r5s9Ue6Ncp8XQ==/base.apk)
        at com.arkivanov.decompose.extensions.compose.jetpack.RootComponentBuilderKt.rememberRootComponent(Unknown Source:15)
        at com.aglushkov.wordteacher.androidApp.MainActivity$setupComposeLayout$1$1$1.invoke(MainActivity.kt:56)
        at com.aglushkov.wordteacher.androidApp.MainActivity$setupComposeLayout$1$1$1.invoke(MainActivity.kt:54)

Got the error here: https://github.com/soniccat/WordTeacher/tree/decomppose_no_such_method_error

I hope this slack thread might help: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1621432061225200?thread_ts=1621431472.224500&cid=CJLTWPH7S

BackPressDispatcher callback wrong order

Callback registered in a component gets called only after the system onBackPressed

Also nested routers stopped working, which might be related to this issue

Looks like a regression from 0.1.0, because the same code works on that version

0.2.0 crashing with compose 0.4.0-build177

Crashlog
Exception in thread "AWT-EventQueue-0" java.lang.NoSuchFieldError: Companion
	at com.arkivanov.decompose.extensions.compose.jetbrains.animation.page.PageAnimationKt$PageAnimationFrame$1$1$1.invoke(PageAnimation.kt:171)
	at com.arkivanov.decompose.extensions.compose.jetbrains.animation.page.PageAnimationKt$PageAnimationFrame$1$1$1.invoke(PageAnimation.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:130)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:46)
	at com.arkivanov.decompose.extensions.compose.jetbrains.animation.child.ComposableSingletons$SlideKt$lambda-1$1.invoke(Slide.kt:18)
	at com.arkivanov.decompose.extensions.compose.jetbrains.animation.child.ComposableSingletons$SlideKt$lambda-1$1.invoke(Slide.kt:17)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:266)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:46)
	at com.arkivanov.decompose.extensions.compose.jetbrains.animation.page.PageAnimationKt$PageAnimationFrame$1.invoke(PageAnimation.kt:121)
	at com.arkivanov.decompose.extensions.compose.jetbrains.animation.page.PageAnimationKt$PageAnimationFrame$1.invoke(PageAnimation.kt:112)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:130)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:46)
	at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1.invoke(BoxWithConstraints.kt:61)
	at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1.invoke(BoxWithConstraints.kt:61)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:46)
	at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1.invoke(SubcomposeLayout.kt:167)
	at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1.invoke(SubcomposeLayout.kt:167)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
	at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:46)
	at androidx.compose.runtime.ComposerKt.invokeComposable(Composer.kt:3433)
	at androidx.compose.runtime.ComposerImpl.composeContent$runtime(Composer.kt:2615)
	at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:348)
	at androidx.compose.runtime.Recomposer.composeInitial$runtime(Recomposer.kt:702)
	at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime(Composer.kt:3039)
	at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:304)
	at androidx.compose.ui.layout.SubcomposeLayoutState.subcomposeInto(SubcomposeLayout.kt:184)
	at androidx.compose.ui.layout.SubcomposeLayoutState.access$subcomposeInto(SubcomposeLayout.kt:100)
	at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:160)
	at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:158)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver.withNoObservations(SnapshotStateObserver.kt:137)
	at androidx.compose.ui.node.OwnerSnapshotObserver.withNoSnapshotReadObservation$ui(OwnerSnapshotObserver.kt:49)
	at androidx.compose.ui.node.LayoutNode.withNoSnapshotReadObservation$ui(LayoutNode.kt:1051)
	at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:158)
	at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:152)
	at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke-0kLqBqw(BoxWithConstraints.kt:61)
	at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke(BoxWithConstraints.kt:59)
	at androidx.compose.ui.layout.SubcomposeLayoutState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:212)
	at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45)
	at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95)
	at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:121)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:75)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:63)
	at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94)
	at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:68)
	at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1169)
	at androidx.compose.foundation.layout.RowColumnImplKt$rowColumnMeasurePolicy$1.measure-3p2s80s(RowColumnImpl.kt:89)
	at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45)
	at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95)
	at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:121)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:75)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:63)
	at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94)
	at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:68)
	at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1169)
	at androidx.compose.foundation.layout.BoxKt$boxMeasurePolicy$1.measure-3p2s80s(Box.kt:111)
	at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45)
	at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:210)
	at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:37)
	at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
	at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:210)
	at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:37)
	at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95)
	at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:121)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:75)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:63)
	at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94)
	at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:68)
	at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1169)
	at androidx.compose.ui.layout.RootMeasurePolicy.measure-3p2s80s(RootMeasurePolicy.kt:38)
	at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45)
	at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
	at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
	at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
	at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
	at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95)
	at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94)
	at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:1782)
	at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:116)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:75)
	at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:63)
	at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94)
	at androidx.compose.ui.node.LayoutNode.remeasure-BRTryo0$ui(LayoutNode.kt:1176)
	at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-0kLqBqw(MeasureAndLayoutDelegate.kt:170)
	at androidx.compose.ui.node.MeasureAndLayoutDelegate.access$doRemeasure-0kLqBqw(MeasureAndLayoutDelegate.kt:39)
	at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:212)
	at androidx.compose.ui.platform.DesktopOwner.measureAndLayout(DesktopOwner.desktop.kt:224)
	at androidx.compose.ui.platform.DesktopOwner.render(DesktopOwner.desktop.kt:207)
	at androidx.compose.ui.platform.DesktopOwners.onFrame(DesktopOwners.desktop.kt:117)
	at androidx.compose.desktop.ComposeLayer$1.onRender(ComposeLayer.desktop.kt:122)
	at org.jetbrains.skiko.SkiaLayer.update(SkiaLayer.kt:188)
	at org.jetbrains.skiko.redrawer.LinuxOpenGLRedrawer.update(LinuxOpenGLRedrawer.kt:48)
	at org.jetbrains.skiko.redrawer.LinuxOpenGLRedrawer.redrawImmediately(LinuxOpenGLRedrawer.kt:39)
	at org.jetbrains.skiko.SkiaLayer.paint(SkiaLayer.kt:131)
	at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
	at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
	at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
	at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
	at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
	at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
	at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
	at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
	at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
	at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5262)
	at java.desktop/javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:246)
	at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
	at java.desktop/javax.swing.JComponent.paint(JComponent.java:1060)
	at java.desktop/java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
	at java.desktop/sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:75)
	at java.desktop/sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:112)
	at java.desktop/java.awt.Container.paint(Container.java:2002)
	at java.desktop/java.awt.Window.paint(Window.java:3933)
	at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:876)
	at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
	at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
	at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
	at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1884)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:316)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

[Survey] Parcelize for Darwin (Apple) targets

I would like to understand, do we need Parcelize support for Darwin (Apple) targets? I built an experimental kotlin-parcelize-darwin compiler plugin, which is similar to kotlin-parcelize. We could enable it in a separate branch and start publishing the experimental version of decompose module, with a version suffix. More info in my article.

Please put ๐Ÿ‘ if you think it is useful, or ๐Ÿ‘Ž if you believe the state preservation is not important on iOS, watchOS, macOS, etc. Please feel free to leave a comment or ask a question.

Runtime crash on Children

I've recently updated to the latest version, and getting a crash when using new Children function:

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/arkivanov/decompose/extensions/compose/jetpack/RouterStateComposableKt$Children$1;
        at com.arkivanov.decompose.extensions.compose.jetpack.RouterStateComposableKt.Children(RouterStateComposable.kt:27)
        at dev.steelahhh.decocrashtester.MainActivity$onCreate$1$1$1.invoke(MainActivity.kt:72)
        at dev.steelahhh.decocrashtester.MainActivity$onCreate$1$1$1.invoke(Unknown Source:10)

I'm using extensions-compose-jetpack in a plain Android module but can repro with a new empty compose project, adding decompose dependencies and using this setup

Router.push is ignored when in the process of transitioning to another component.

I've found a bug where a router push event is ignored when performed during an ongoing navigation.

I haven't migrated to the latest Kotlin yet, so I'm still on Decompose 0.1.7, and Kotlin 1.4.21-2

Here is the situation:
I have a RootComponent, which has 3 child components, A, B, and C.

We start the app by displaying A where an auth occurs

router.navigate { listOf(Screen.A) }

After the user logs in, we navigate to Screen B, and remove A from the backstack:

router.navigate { listOf(Screen.B) }

Inside of Component B, I was trying to debug something and so I called

    init {
        lifecycle.doOnResume {
            resumePauseLaunch { loadData() }
            output(Output.ActionThatNavigatesToC)
        }
    }

Which ultimately triggers this in the root component:

router.push(Screen.C)

Even though C is the last screen pushed to, the View isn't updated and it just stays on Screen B. Calling output(Output.ActionThatNavigatesToC) after the screen transition to B has completed, works as intended.

Message me on Slack, and I can step you through the code if you'd like more details.

Can we expect JS platform support for todo app too?

I know there is js support for counter app , but to me TODO app's code and structure seems more lucid and I built desktop and android app learning from todo code , I was hoping if you have any plans to build a jsReact UI for todo app too?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.