diff --git a/build.gradle.kts b/build.gradle.kts index 19c309e05..780291ffb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,6 +21,7 @@ buildscript { classpath(deps.jetbrains.compose.composeGradlePlug) classpath(deps.jetbrains.kotlinx.binaryCompatibilityValidator) classpath(deps.parcelizeDarwin.gradlePlug) + classpath(deps.jetbrains.kotlin.serializationGradlePlug) } } diff --git a/decompose/api/android/decompose.api b/decompose/api/android/decompose.api index b0509a57b..ffcf8d4b7 100644 --- a/decompose/api/android/decompose.api +++ b/decompose/api/android/decompose.api @@ -82,6 +82,14 @@ public final class com/arkivanov/decompose/errorhandler/ErrorHandlersKt { public static final fun setOnDecomposeError (Lkotlin/jvm/functions/Function1;)V } +public final class com/arkivanov/decompose/router/ParcelableJson$Creator : android/os/Parcelable$Creator { + public fun ()V + public final fun createFromParcel (Landroid/os/Parcel;)Lcom/arkivanov/decompose/router/ParcelableJson; + public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; + public final fun newArray (I)[Lcom/arkivanov/decompose/router/ParcelableJson; + public synthetic fun newArray (I)[Ljava/lang/Object; +} + public abstract interface class com/arkivanov/decompose/router/children/ChildNavState { public abstract fun getConfiguration ()Ljava/lang/Object; public abstract fun getStatus ()Lcom/arkivanov/decompose/router/children/ChildNavState$Status; @@ -98,7 +106,9 @@ public final class com/arkivanov/decompose/router/children/ChildNavState$Status public final class com/arkivanov/decompose/router/children/ChildrenFactoryKt { public static final fun children (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun children (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun children$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun children$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; } public abstract interface class com/arkivanov/decompose/router/children/NavState { @@ -208,8 +218,10 @@ public final class com/arkivanov/decompose/router/pages/ChildPages { public final class com/arkivanov/decompose/router/pages/ChildPagesFactoryKt { public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; public static final fun getDefaultPageStatus (ILcom/arkivanov/decompose/router/pages/Pages;)Lcom/arkivanov/decompose/router/children/ChildNavState$Status; } @@ -288,8 +300,10 @@ public final class com/arkivanov/decompose/router/slot/ChildSlot { public final class com/arkivanov/decompose/router/slot/ChildSlotFactoryKt { public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; } public abstract interface class com/arkivanov/decompose/router/slot/SlotNavigation : com/arkivanov/decompose/router/slot/SlotNavigationSource, com/arkivanov/decompose/router/slot/SlotNavigator { @@ -344,8 +358,12 @@ public final class com/arkivanov/decompose/router/stack/ChildStack { public final class com/arkivanov/decompose/router/stack/ChildStackFactoryKt { public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/reflect/KClass;Ljava/lang/String;ZZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/reflect/KClass;Ljava/lang/String;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; } public abstract interface class com/arkivanov/decompose/router/stack/StackNavigation : com/arkivanov/decompose/router/stack/StackNavigationSource, com/arkivanov/decompose/router/stack/StackNavigator { diff --git a/decompose/api/jvm/decompose.api b/decompose/api/jvm/decompose.api index a088b2da1..1b2244013 100644 --- a/decompose/api/jvm/decompose.api +++ b/decompose/api/jvm/decompose.api @@ -84,7 +84,9 @@ public final class com/arkivanov/decompose/router/children/ChildNavState$Status public final class com/arkivanov/decompose/router/children/ChildrenFactoryKt { public static final fun children (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun children (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun children$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun children$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; } public abstract interface class com/arkivanov/decompose/router/children/NavState { @@ -186,8 +188,10 @@ public final class com/arkivanov/decompose/router/pages/ChildPages { public final class com/arkivanov/decompose/router/pages/ChildPagesFactoryKt { public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/pages/PagesNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; public static final fun getDefaultPageStatus (ILcom/arkivanov/decompose/router/pages/Pages;)Lcom/arkivanov/decompose/router/children/ChildNavState$Status; } @@ -258,8 +262,10 @@ public final class com/arkivanov/decompose/router/slot/ChildSlot { public final class com/arkivanov/decompose/router/slot/ChildSlotFactoryKt { public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlin/reflect/KClass;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/slot/SlotNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; } public abstract interface class com/arkivanov/decompose/router/slot/SlotNavigation : com/arkivanov/decompose/router/slot/SlotNavigationSource, com/arkivanov/decompose/router/slot/SlotNavigator { @@ -314,8 +320,12 @@ public final class com/arkivanov/decompose/router/stack/ChildStack { public final class com/arkivanov/decompose/router/stack/ChildStackFactoryKt { public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/reflect/KClass;Ljava/lang/String;ZZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; + public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/reflect/KClass;Ljava/lang/String;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; + public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/stack/StackNavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value; } public abstract interface class com/arkivanov/decompose/router/stack/StackNavigation : com/arkivanov/decompose/router/stack/StackNavigationSource, com/arkivanov/decompose/router/stack/StackNavigator { diff --git a/decompose/build.gradle.kts b/decompose/build.gradle.kts index f63ca0681..9b3838c50 100644 --- a/decompose/build.gradle.kts +++ b/decompose/build.gradle.kts @@ -9,6 +9,7 @@ import com.arkivanov.gradle.setupSourceSets plugins { id("kotlin-multiplatform") id("com.android.library") + id("kotlinx-serialization") id("kotlin-parcelize") id("com.arkivanov.parcelize.darwin") id("com.arkivanov.gradle.setup") @@ -51,6 +52,8 @@ kotlin { api(deps.essenty.stateKeeper) api(deps.essenty.instanceKeeper) api(deps.essenty.backHandler) + api(deps.jetbrains.kotlinx.kotlinxSerializationCore) + implementation(deps.jetbrains.kotlinx.kotlinxSerializationJson) } common.test.dependencies { diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ParcelizeDeprecatedMessage.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ParcelizeDeprecatedMessage.kt new file mode 100644 index 000000000..5c7d269bb --- /dev/null +++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ParcelizeDeprecatedMessage.kt @@ -0,0 +1,4 @@ +package com.arkivanov.decompose + +internal const val PARCELIZE_DEPRECATED_MESSAGE = + "Parcelize compiler plugin will not work with KMP and K2 compiler. Please use similar API based on kotlinx-serialization." diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/SavedData.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/SavedData.kt new file mode 100644 index 000000000..5d89739d7 --- /dev/null +++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/SavedData.kt @@ -0,0 +1,32 @@ +package com.arkivanov.decompose.router + +import com.arkivanov.essenty.parcelable.Parcelable +import com.arkivanov.essenty.parcelable.ParcelableContainer +import com.arkivanov.essenty.parcelable.Parcelize +import com.arkivanov.essenty.parcelable.consumeRequired +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.json.Json + +private val json = + Json { + allowStructuredMapKeys = true + } + +@Parcelize +private class ParcelableJson(val json: String) : Parcelable + +// Temporary interop until v3.0 +internal fun T.toParcelableContainer(strategy: SerializationStrategy): ParcelableContainer = + ParcelableContainer( + value = ParcelableJson( + json = json.encodeToString(serializer = strategy, value = this), + ), + ) + +// Temporary interop until v3.0 +internal fun ParcelableContainer.consumeRequired(strategy: DeserializationStrategy): T = + json.decodeFromString( + deserializer = strategy, + string = consumeRequired().json, + ) diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt index 3e5136894..9558edb81 100644 --- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt +++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt @@ -2,7 +2,10 @@ package com.arkivanov.decompose.router.children import com.arkivanov.decompose.Child import com.arkivanov.decompose.ComponentContext +import com.arkivanov.decompose.PARCELIZE_DEPRECATED_MESSAGE import com.arkivanov.decompose.backhandler.child +import com.arkivanov.decompose.router.consumeRequired +import com.arkivanov.decompose.router.toParcelableContainer import com.arkivanov.decompose.value.MutableValue import com.arkivanov.decompose.value.Value import com.arkivanov.essenty.backhandler.BackCallback @@ -13,6 +16,50 @@ import com.arkivanov.essenty.parcelable.ParcelableContainer import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.essenty.parcelable.consumeRequired import com.arkivanov.essenty.statekeeper.consume +import kotlinx.serialization.KSerializer + +/** + * A convenience method for the main [children] method. Allows having `Serializable` navigation state [N], + * so it's automatically saved and restored. This method can be used if the custom save/restore logic + * is not required. + */ +fun ComponentContext.children( + source: NavigationSource, + stateSerializer: KSerializer?, + initialState: () -> N, + key: String, + navTransformer: (state: N, event: E) -> N, + stateMapper: (state: N, children: List>) -> S, + onStateChanged: (newState: N, oldState: N?) -> Unit = { _, _ -> }, + onEventComplete: (event: E, newState: N, oldState: N) -> Unit = { _, _, _ -> }, + backTransformer: (state: N) -> (() -> N)? = { null }, + childFactory: (configuration: C, componentContext: ComponentContext) -> T, +): Value where N : NavState, N : Any = + children( + source = source, + saveState = { state -> + if (stateSerializer != null) { + state.toParcelableContainer(strategy = stateSerializer) + } else { + null + } + }, + restoreState = { container -> + if (stateSerializer != null) { + container.consumeRequired(strategy = stateSerializer) + } else { + null + } + }, + initialState = initialState, + key = key, + navTransformer = navTransformer, + stateMapper = stateMapper, + onStateChanged = onStateChanged, + onEventComplete = onEventComplete, + backTransformer = backTransformer, + childFactory = childFactory, + ) /** * Initialised and manages a generic list of components. This is an API for custom navigation models. @@ -151,6 +198,8 @@ fun , S : Any> ComponentContext.child * so it's automatically saved and restored. This method can be used if the custom save/restore logic * is not required. */ +@Suppress("DeprecatedCallableAddReplaceWith") +@Deprecated(message = PARCELIZE_DEPRECATED_MESSAGE) inline fun ComponentContext.children( source: NavigationSource, key: String, diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPagesFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPagesFactory.kt index 9e9a61364..49792ee67 100644 --- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPagesFactory.kt +++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPagesFactory.kt @@ -2,18 +2,87 @@ package com.arkivanov.decompose.router.pages import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.ExperimentalDecomposeApi +import com.arkivanov.decompose.PARCELIZE_DEPRECATED_MESSAGE import com.arkivanov.decompose.router.children.ChildNavState import com.arkivanov.decompose.router.children.ChildNavState.Status import com.arkivanov.decompose.router.children.NavState import com.arkivanov.decompose.router.children.SimpleChildNavState import com.arkivanov.decompose.router.children.children +import com.arkivanov.decompose.router.consumeRequired +import com.arkivanov.decompose.router.toParcelableContainer import com.arkivanov.decompose.value.Value import com.arkivanov.essenty.parcelable.Parcelable import com.arkivanov.essenty.parcelable.ParcelableContainer import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.essenty.parcelable.consumeRequired +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable import kotlin.reflect.KClass +/** + * Initializes and manages a list of components with one selected (active) component. + * The list can be empty. + * + * @param source a source of navigation events. + * @param serializer an optional [KSerializer] to be used for serializing and deserializing configurations. + * If `null` then the navigation state will not be preserved. + * @param initialPages an initial state of Child Pages that should be set + * if there is no saved state. See [Pages] for more information. + * @param key a key of the list, must be unique if there are multiple Child Pages used in + * the same component. + * @param pageStatus a function that returns a [Status] of a page at a given index. + * By default, the currently selected page is [Status.ACTIVE], its two neighbours + * are [Status.INACTIVE], and the rest are [Status.DESTROYED]. You can implement your own + * logic, for example with circular behaviour. + * @param handleBackButton determines whether the previous component should be automatically + * selected on back button press or not, default is `false`. + * @param childFactory a factory function that creates new child instances. + * @return an observable [Value] of [ChildPages]. + */ +@ExperimentalDecomposeApi +fun ComponentContext.childPages( + source: PagesNavigationSource, + serializer: KSerializer?, + initialPages: () -> Pages = { Pages() }, + key: String = "DefaultChildPages", + pageStatus: (index: Int, Pages) -> Status = ::getDefaultPageStatus, + handleBackButton: Boolean = false, + childFactory: (configuration: C, ComponentContext) -> T, +): Value> = + childPages( + source = source, + savePages = { pages -> + if (serializer != null) { + SerializablePages(items = pages.items, selectedIndex = pages.selectedIndex) + .toParcelableContainer(strategy = SerializablePages.serializer(serializer)) + } else { + null + } + }, + restorePages = { container -> + if (serializer != null) { + val pages = container.consumeRequired(strategy = SerializablePages.serializer(serializer)) + Pages( + items = pages.items, + selectedIndex = pages.selectedIndex, + ) + } else { + null + } + }, + initialPages = initialPages, + key = key, + pageStatus = pageStatus, + handleBackButton = handleBackButton, + childFactory = childFactory, + ) + +@Serializable +private class SerializablePages( + val items: List, + val selectedIndex: Int, +) + /** * Initializes and manages a list of components with one selected (active) component. * The list can be empty. @@ -34,6 +103,8 @@ import kotlin.reflect.KClass * @param childFactory a factory function that creates new child instances. * @return an observable [Value] of [ChildPages]. */ +@Suppress("DeprecatedCallableAddReplaceWith", "DEPRECATION") +@Deprecated(message = PARCELIZE_DEPRECATED_MESSAGE) @ExperimentalDecomposeApi inline fun ComponentContext.childPages( source: PagesNavigationSource, @@ -76,6 +147,7 @@ inline fun ComponentContext.childPages( * @param childFactory a factory function that creates new child instances. * @return an observable [Value] of [ChildPages]. */ +@Deprecated(message = PARCELIZE_DEPRECATED_MESSAGE) @ExperimentalDecomposeApi fun ComponentContext.childPages( source: PagesNavigationSource, diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/slot/ChildSlotFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/slot/ChildSlotFactory.kt index 7383aa901..0c82404fa 100644 --- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/slot/ChildSlotFactory.kt +++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/slot/ChildSlotFactory.kt @@ -2,15 +2,64 @@ package com.arkivanov.decompose.router.slot import com.arkivanov.decompose.Child import com.arkivanov.decompose.ComponentContext +import com.arkivanov.decompose.PARCELIZE_DEPRECATED_MESSAGE import com.arkivanov.decompose.router.children.ChildNavState.Status import com.arkivanov.decompose.router.children.NavState import com.arkivanov.decompose.router.children.SimpleChildNavState import com.arkivanov.decompose.router.children.children +import com.arkivanov.decompose.router.consumeRequired +import com.arkivanov.decompose.router.toParcelableContainer import com.arkivanov.decompose.value.Value import com.arkivanov.essenty.parcelable.Parcelable import com.arkivanov.essenty.parcelable.ParcelableContainer +import kotlinx.serialization.KSerializer import kotlin.reflect.KClass +/** + * Initializes and manages a slot for one child component. + * The child component can be either active or dismissed (destroyed). + * + * @param source a source of navigation events. + * @param serializer an optional [KSerializer] to be used for serializing and deserializing configurations. + * If `null` then the navigation state will not be preserved. + * @param key a key of the slot, must be unique within the parent (hosting) component. + * @param initialConfiguration a component configuration that should be shown if there is + * no saved state, return `null` to show nothing. + * @param handleBackButton determines whether the child component should be automatically dismissed + * on back button press or not, default is `false`. + * @param childFactory a factory function that creates new child instances. + * @return an observable [Value] of [ChildSlot]. + */ +fun ComponentContext.childSlot( + source: SlotNavigationSource, + serializer: KSerializer?, + initialConfiguration: () -> C? = { null }, + key: String = "DefaultChildSlot", + handleBackButton: Boolean = false, + childFactory: (configuration: C, ComponentContext) -> T, +): Value> = + childSlot( + source = source, + saveConfiguration = { configuration -> + if ((serializer != null) && (configuration != null)) { + configuration.toParcelableContainer(strategy = serializer) + } else { + null + } + }, + restoreConfiguration = { container -> + if (serializer != null) { + container.consumeRequired(strategy = serializer) + } else { + null + } + }, + key = key, + initialConfiguration = initialConfiguration, + handleBackButton = handleBackButton, + childFactory = childFactory, + ) + /** * Initializes and manages a slot for one child component. * The child component can be either active or dismissed (destroyed). @@ -27,6 +76,8 @@ import kotlin.reflect.KClass * @param childFactory a factory function that creates new child instances. * @return an observable [Value] of [ChildSlot]. */ +@Suppress("DeprecatedCallableAddReplaceWith") +@Deprecated(message = PARCELIZE_DEPRECATED_MESSAGE) fun ComponentContext.childSlot( source: SlotNavigationSource, configurationClass: KClass, diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStackFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStackFactory.kt index 63740fb46..675beba0a 100644 --- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStackFactory.kt +++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStackFactory.kt @@ -2,17 +2,87 @@ package com.arkivanov.decompose.router.stack import com.arkivanov.decompose.Child import com.arkivanov.decompose.ComponentContext +import com.arkivanov.decompose.PARCELIZE_DEPRECATED_MESSAGE import com.arkivanov.decompose.router.children.ChildNavState.Status import com.arkivanov.decompose.router.children.NavState import com.arkivanov.decompose.router.children.SimpleChildNavState import com.arkivanov.decompose.router.children.children +import com.arkivanov.decompose.router.consumeRequired +import com.arkivanov.decompose.router.toParcelableContainer import com.arkivanov.decompose.value.Value import com.arkivanov.essenty.parcelable.Parcelable import com.arkivanov.essenty.parcelable.ParcelableContainer import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.essenty.parcelable.consumeRequired +import kotlinx.serialization.KSerializer +import kotlinx.serialization.builtins.ListSerializer import kotlin.reflect.KClass +/** + * Initializes and manages a stack of components. + * + * @param source a source of navigation events. + * @param serializer an optional [KSerializer] to be used for serializing and deserializing configurations. + * If `null` then the navigation state will not be preserved. + * @param initialStack a stack of component configurations (ordered from tail to head) that should be set + * if there is no saved state, must be not empty and unique. + * @param key a key of the stack, must be unique if there are multiple stacks in the same component. + * @param handleBackButton determines whether the stack should be automatically popped on back button press or not, + * default is `false`. + * @param childFactory a factory function that creates new child instances. + * @return an observable [Value] of [ChildStack]. + */ +fun ComponentContext.childStack( + source: StackNavigationSource, + serializer: KSerializer?, + initialStack: () -> List, + key: String = "DefaultChildStack", + handleBackButton: Boolean = false, + childFactory: (configuration: C, ComponentContext) -> T, +): Value> = + childStack( + source = source, + saveStack = { stack -> + if (serializer != null) { + stack.toParcelableContainer(strategy = ListSerializer(serializer)) + } else { + null + } + }, + restoreStack = { container -> + if (serializer != null) { + container.consumeRequired(strategy = ListSerializer(serializer)) + } else { + null + } + }, + initialStack = initialStack, + key = key, + handleBackButton = handleBackButton, + childFactory = childFactory, + ) + +/** + * A convenience extension function for [ComponentContext.childStack]. + */ +@Suppress("DeprecatedCallableAddReplaceWith") +fun ComponentContext.childStack( + source: StackNavigationSource, + serializer: KSerializer?, + initialConfiguration: C, + key: String = "DefaultChildStack", + handleBackButton: Boolean = false, + childFactory: (configuration: C, ComponentContext) -> T +): Value> = + childStack( + source = source, + serializer = serializer, + initialStack = { listOf(initialConfiguration) }, + key = key, + handleBackButton = handleBackButton, + childFactory = childFactory, + ) + /** * Initializes and manages a stack of components. * @@ -28,6 +98,7 @@ import kotlin.reflect.KClass * @param childFactory a factory function that creates new child instances. * @return an observable [Value] of [ChildStack]. */ +@Deprecated(message = PARCELIZE_DEPRECATED_MESSAGE) fun ComponentContext.childStack( source: StackNavigationSource, initialStack: () -> List, diff --git a/deps.versions.toml b/deps.versions.toml index b1df4e0e4..b077f18dd 100644 --- a/deps.versions.toml +++ b/deps.versions.toml @@ -1,14 +1,15 @@ [versions] -decompose = "2.1.0" +decompose = "2.2.0-dev02" kotlin = "1.9.10" -essenty = "1.2.0" -parcelizeDarwin = "0.2.1" +essenty = "1.3.0-alpha01" +parcelizeDarwin = "0.2.2" reaktive = "1.2.3" junit = "4.13.2" jetbrainsCompose = "1.5.1" jetbrainsKotlinWrappers = "1.0.0-pre.608" jetbrainsKotlinxCoroutines = "1.6.4" +jetbrainsKotlinxSerialization = "1.6.0" jetbrainsBinaryCompatibilityValidator = "0.13.2" jetpackCompose = "1.5.0" jetpackComposeCompiler = "1.5.3" @@ -46,6 +47,9 @@ jetbrains-kotlinWrappers-kotlinWrappersBom = { group = "org.jetbrains.kotlin-wra jetbrains-kotlinx-binaryCompatibilityValidator = { group = "org.jetbrains.kotlinx", name = "binary-compatibility-validator", version.ref = "jetbrainsBinaryCompatibilityValidator" } jetbrains-kotlinx-kotlinxCoroutinesCore = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "jetbrainsKotlinxCoroutines" } jetbrains-kotlinx-kotlinxCoroutinesSwing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "jetbrainsKotlinxCoroutines" } +jetbrains-kotlin-serializationGradlePlug = { group = "org.jetbrains.kotlin", name = "kotlin-serialization", version.ref = "kotlin" } +jetbrains-kotlinx-kotlinxSerializationCore = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core", version.ref = "jetbrainsKotlinxSerialization" } +jetbrains-kotlinx-kotlinxSerializationJson = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "jetbrainsKotlinxSerialization" } androidx-compose-foundation-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "jetpackCompose" } androidx-compose-ui-uiTestJunit4 = { group = "androidx.compose.ui", name = "ui-test-junit4", version.ref = "jetpackCompose" } diff --git a/sample/shared/shared/build.gradle.kts b/sample/shared/shared/build.gradle.kts index bfa6e918f..a85ef6885 100644 --- a/sample/shared/shared/build.gradle.kts +++ b/sample/shared/shared/build.gradle.kts @@ -10,7 +10,7 @@ plugins { id("kotlin-multiplatform") id("com.android.library") id("kotlin-parcelize") - id("com.arkivanov.parcelize.darwin") // Optional, only if you need state preservation on Darwin (Apple) targets + id("kotlinx-serialization") id("com.arkivanov.gradle.setup") } diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/cards/DefaultCardsComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/cards/DefaultCardsComponent.kt index cd42866d0..b3230cdff 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/cards/DefaultCardsComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/cards/DefaultCardsComponent.kt @@ -9,10 +9,9 @@ import com.arkivanov.decompose.router.stack.navigate import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.router.stack.push import com.arkivanov.decompose.value.Value -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.sample.shared.cards.card.CardComponent import com.arkivanov.sample.shared.cards.card.DefaultCardComponent +import kotlinx.serialization.Serializable class DefaultCardsComponent( componentContext: ComponentContext, @@ -23,6 +22,7 @@ class DefaultCardsComponent( private val _stack: Value> = childStack( source = navigation, + serializer = Config.serializer(), initialStack = { COLORS.mapIndexed { index, color -> Config(color = color, number = index + 1) @@ -76,9 +76,9 @@ class DefaultCardsComponent( ) } - @Parcelize + @Serializable private data class Config( val color: Long, val number: Int, - ) : Parcelable + ) } diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/cards/card/DefaultCardComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/cards/card/DefaultCardComponent.kt index 73306f058..a26be906d 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/cards/card/DefaultCardComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/cards/card/DefaultCardComponent.kt @@ -7,9 +7,6 @@ import com.arkivanov.decompose.value.update import com.arkivanov.essenty.instancekeeper.InstanceKeeper import com.arkivanov.essenty.instancekeeper.getOrCreate import com.arkivanov.essenty.lifecycle.subscribe -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize -import com.arkivanov.essenty.statekeeper.consume import com.arkivanov.sample.shared.cards.card.CardComponent.Model import com.badoo.reaktive.disposable.Disposable import com.badoo.reaktive.disposable.scope.DisposableScope @@ -19,6 +16,7 @@ import com.badoo.reaktive.scheduler.Scheduler import com.badoo.reaktive.scheduler.mainScheduler import com.badoo.reaktive.subject.behavior.BehaviorObservable import com.badoo.reaktive.subject.behavior.BehaviorSubject +import kotlinx.serialization.Serializable class DefaultCardComponent( componentContext: ComponentContext, @@ -30,7 +28,7 @@ class DefaultCardComponent( private val handler = instanceKeeper.getOrCreate { Handler( - initialCount = stateKeeper.consume(key = KEY_SAVED_STATE)?.count ?: 0, + initialCount = stateKeeper.consume(key = KEY_SAVED_STATE, strategy = SavedState.serializer())?.count ?: 0, tickScheduler = tickScheduler, ) } @@ -39,7 +37,7 @@ class DefaultCardComponent( override val model: Value = _model init { - stateKeeper.register(KEY_SAVED_STATE) { SavedState(count = handler.count.value) } + stateKeeper.register(key = KEY_SAVED_STATE, strategy = SavedState.serializer()) { SavedState(count = handler.count.value) } handler.count.subscribeScoped { count -> _model.update { it.copy(text = "Count: $count") } @@ -92,6 +90,6 @@ class DefaultCardComponent( } } - @Parcelize - private class SavedState(val count: Int) : Parcelable + @Serializable + private class SavedState(val count: Int) } diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/DefaultCountersComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/DefaultCountersComponent.kt index 8b24c2514..1edfd29b3 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/DefaultCountersComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/DefaultCountersComponent.kt @@ -8,10 +8,9 @@ import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.router.stack.popTo import com.arkivanov.decompose.router.stack.push import com.arkivanov.decompose.value.Value -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.sample.shared.counters.counter.CounterComponent import com.arkivanov.sample.shared.counters.counter.DefaultCounterComponent +import kotlinx.serialization.Serializable internal class DefaultCountersComponent( componentContext: ComponentContext, @@ -22,6 +21,7 @@ internal class DefaultCountersComponent( private val _childStack = childStack( source = navigation, + serializer = Config.serializer(), initialConfiguration = Config(index = 0, isBackEnabled = false), childFactory = ::child, ) @@ -48,9 +48,9 @@ internal class DefaultCountersComponent( navigation.popTo(index = toIndex) } - @Parcelize + @Serializable private data class Config( val index: Int, val isBackEnabled: Boolean, - ) : Parcelable + ) } diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/counter/DefaultCounterComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/counter/DefaultCounterComponent.kt index c0ded2381..f3ef8ba34 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/counter/DefaultCounterComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/counter/DefaultCounterComponent.kt @@ -12,9 +12,6 @@ import com.arkivanov.decompose.value.operator.map import com.arkivanov.decompose.value.update import com.arkivanov.essenty.instancekeeper.InstanceKeeper import com.arkivanov.essenty.instancekeeper.getOrCreate -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize -import com.arkivanov.essenty.statekeeper.consume import com.arkivanov.sample.shared.counters.counter.CounterComponent.Model import com.arkivanov.sample.shared.dialog.DefaultDialogComponent import com.arkivanov.sample.shared.dialog.DialogComponent @@ -22,6 +19,7 @@ import com.badoo.reaktive.disposable.scope.DisposableScope import com.badoo.reaktive.observable.observableInterval import com.badoo.reaktive.scheduler.Scheduler import com.badoo.reaktive.scheduler.mainScheduler +import kotlinx.serialization.Serializable internal class DefaultCounterComponent( componentContext: ComponentContext, @@ -35,7 +33,7 @@ internal class DefaultCounterComponent( private val handler = instanceKeeper.getOrCreate(KEY_STATE) { Handler( - initialState = stateKeeper.consume(KEY_STATE) ?: State(), + initialState = stateKeeper.consume(key = KEY_STATE, strategy = State.serializer()) ?: State(), tickScheduler = tickScheduler, ) } @@ -47,7 +45,7 @@ internal class DefaultCounterComponent( private val _dialogSlot = childSlot( source = dialogNavigation, - persistent = false, + serializer = null, handleBackButton = true, childFactory = { config, _ -> DefaultDialogComponent( @@ -65,7 +63,7 @@ internal class DefaultCounterComponent( } init { - stateKeeper.register(KEY_STATE) { handler.state.value } + stateKeeper.register(key = KEY_STATE, strategy = State.serializer()) { handler.state.value } } private fun State.toModel(): Model = @@ -90,15 +88,15 @@ internal class DefaultCounterComponent( private const val KEY_STATE = "STATE" } - @Parcelize + @Serializable private data class State( val count: Int = 0, - ) : Parcelable + ) - @Parcelize + @Serializable private data class DialogConfig( val count: Int, - ) : Parcelable + ) private class Handler( initialState: State, diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/customnavigation/DefaultCustomNavigationComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/customnavigation/DefaultCustomNavigationComponent.kt index 28ea73f39..07897b816 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/customnavigation/DefaultCustomNavigationComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/customnavigation/DefaultCustomNavigationComponent.kt @@ -8,11 +8,10 @@ import com.arkivanov.decompose.router.children.SimpleChildNavState import com.arkivanov.decompose.router.children.SimpleNavigation import com.arkivanov.decompose.router.children.children import com.arkivanov.decompose.value.Value -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.sample.shared.customnavigation.CustomNavigationComponent.Children import com.arkivanov.sample.shared.customnavigation.CustomNavigationComponent.Mode import com.arkivanov.sample.shared.customnavigation.KittenComponent.ImageType +import kotlinx.serialization.Serializable class DefaultCustomNavigationComponent( componentContext: ComponentContext, @@ -23,6 +22,7 @@ class DefaultCustomNavigationComponent( private val _children: Value> = children( source = navigation, + stateSerializer = NavigationState.serializer(), key = "carousel", initialState = { NavigationState( @@ -87,25 +87,25 @@ class DefaultCustomNavigationComponent( } } - @Parcelize + @Serializable private data class Config( val imageType: ImageType, - ) : Parcelable + ) - @Parcelize + @Serializable private data class NavigationState( val configurations: List, val index: Int, val mode: Mode, - ) : NavState, Parcelable { + ) : NavState { - override val children: List> - get() = - configurations.mapIndexed { index, config -> - SimpleChildNavState( - configuration = config, - status = if (index == this.index) ChildNavState.Status.ACTIVE else ChildNavState.Status.INACTIVE, - ) - } + override val children: List> by lazy { + configurations.mapIndexed { index, config -> + SimpleChildNavState( + configuration = config, + status = if (index == this.index) ChildNavState.Status.ACTIVE else ChildNavState.Status.INACTIVE, + ) + } + } } } diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/customnavigation/DefaultKittenComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/customnavigation/DefaultKittenComponent.kt index ea997c406..47156142c 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/customnavigation/DefaultKittenComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/customnavigation/DefaultKittenComponent.kt @@ -8,15 +8,13 @@ import com.arkivanov.decompose.value.update import com.arkivanov.essenty.instancekeeper.InstanceKeeper import com.arkivanov.essenty.instancekeeper.getOrCreate import com.arkivanov.essenty.lifecycle.subscribe -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize -import com.arkivanov.essenty.statekeeper.consume import com.arkivanov.sample.shared.customnavigation.KittenComponent.ImageType import com.arkivanov.sample.shared.customnavigation.KittenComponent.Model import com.badoo.reaktive.disposable.Disposable import com.badoo.reaktive.observable.observableInterval import com.badoo.reaktive.observable.subscribe import com.badoo.reaktive.scheduler.mainScheduler +import kotlinx.serialization.Serializable class DefaultKittenComponent( componentContext: ComponentContext, @@ -25,7 +23,7 @@ class DefaultKittenComponent( private val handler = instanceKeeper.getOrCreate(KEY_STATE) { - Handler(initialState = stateKeeper.consume(KEY_STATE) ?: State()) + Handler(initialState = stateKeeper.consume(key = KEY_STATE, strategy = State.serializer()) ?: State()) } override val model: Value = handler.state.map { it.toModel() } @@ -36,7 +34,7 @@ class DefaultKittenComponent( onStop = handler::pause, ) - stateKeeper.register(KEY_STATE) { handler.state.value } + stateKeeper.register(key = KEY_STATE, strategy = State.serializer()) { handler.state.value } } private fun State.toModel(): Model = @@ -49,10 +47,10 @@ class DefaultKittenComponent( private const val KEY_STATE = "STATE" } - @Parcelize + @Serializable private data class State( val count: Int = 0, - ) : Parcelable + ) private class Handler(initialState: State) : InstanceKeeper.Instance { val state: MutableValue = MutableValue(initialState) diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/dynamicfeatures/DefaultDynamicFeaturesComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/dynamicfeatures/DefaultDynamicFeaturesComponent.kt index e27163dc6..879c9eef2 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/dynamicfeatures/DefaultDynamicFeaturesComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/dynamicfeatures/DefaultDynamicFeaturesComponent.kt @@ -7,8 +7,6 @@ import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.router.stack.push import com.arkivanov.decompose.value.Value -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.sample.shared.dynamicfeatures.DynamicFeaturesComponent.Child import com.arkivanov.sample.shared.dynamicfeatures.DynamicFeaturesComponent.Child.Feature1Child import com.arkivanov.sample.shared.dynamicfeatures.DynamicFeaturesComponent.Child.Feature2Child @@ -17,6 +15,7 @@ import com.arkivanov.sample.shared.dynamicfeatures.dynamicfeature.DynamicFeature import com.arkivanov.sample.shared.dynamicfeatures.dynamicfeature.FeatureInstaller import com.arkivanov.sample.shared.dynamicfeatures.feature1.Feature1 import com.arkivanov.sample.shared.dynamicfeatures.feature2.Feature2 +import kotlinx.serialization.Serializable import kotlin.random.Random internal class DefaultDynamicFeaturesComponent( @@ -29,6 +28,7 @@ internal class DefaultDynamicFeaturesComponent( private val stack = childStack( source = navigation, + serializer = Config.serializer(), initialConfiguration = Config.Feature1, handleBackButton = true, childFactory = ::child, @@ -69,11 +69,12 @@ internal class DefaultDynamicFeaturesComponent( } ) - private sealed interface Config : Parcelable { - @Parcelize + @Serializable + private sealed interface Config { + @Serializable data object Feature1 : Config - @Parcelize + @Serializable data class Feature2(val magicNumber: Int) : Config } } diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/dynamicfeatures/dynamicfeature/DefaultDynamicFeatureComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/dynamicfeatures/dynamicfeature/DefaultDynamicFeatureComponent.kt index e7ff01f36..606572071 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/dynamicfeatures/dynamicfeature/DefaultDynamicFeatureComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/dynamicfeatures/dynamicfeature/DefaultDynamicFeatureComponent.kt @@ -7,14 +7,13 @@ import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.replaceCurrent import com.arkivanov.decompose.value.Value import com.arkivanov.essenty.lifecycle.subscribe -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.sample.shared.dynamicfeatures.dynamicfeature.DynamicFeatureComponent.Child import com.arkivanov.sample.shared.dynamicfeatures.dynamicfeature.DynamicFeatureComponent.Child.ErrorChild import com.arkivanov.sample.shared.dynamicfeatures.dynamicfeature.DynamicFeatureComponent.Child.FeatureChild import com.arkivanov.sample.shared.dynamicfeatures.dynamicfeature.DynamicFeatureComponent.Child.LoadingChild import com.badoo.reaktive.disposable.scope.DisposableScope import com.badoo.reaktive.disposable.scope.disposableScope +import kotlinx.serialization.Serializable internal class DefaultDynamicFeatureComponent( componentContext: ComponentContext, @@ -28,6 +27,7 @@ internal class DefaultDynamicFeatureComponent( private val stack = childStack( source = navigation, + serializer = Config.serializer(), initialConfiguration = Config.Loading, childFactory = ::child, ) @@ -62,14 +62,15 @@ internal class DefaultDynamicFeatureComponent( } } - private sealed interface Config : Parcelable { - @Parcelize + @Serializable + private sealed interface Config { + @Serializable data object Loading : Config - @Parcelize + @Serializable data object Feature : Config - @Parcelize + @Serializable data object Error : Config } } diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/multipane/DefaultMultiPaneComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/multipane/DefaultMultiPaneComponent.kt index d14967342..e3ff541c4 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/multipane/DefaultMultiPaneComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/multipane/DefaultMultiPaneComponent.kt @@ -9,8 +9,6 @@ import com.arkivanov.decompose.router.children.SimpleChildNavState import com.arkivanov.decompose.router.children.SimpleNavigation import com.arkivanov.decompose.router.children.children import com.arkivanov.decompose.value.Value -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.sample.shared.multipane.MultiPaneComponent.Children import com.arkivanov.sample.shared.multipane.database.DefaultArticleDatabase import com.arkivanov.sample.shared.multipane.details.ArticleDetailsComponent @@ -22,6 +20,7 @@ import com.badoo.reaktive.disposable.scope.DisposableScope import com.badoo.reaktive.observable.map import com.badoo.reaktive.observable.notNull import com.badoo.reaktive.subject.behavior.BehaviorSubject +import kotlinx.serialization.Serializable internal class DefaultMultiPaneComponent( componentContext: ComponentContext @@ -34,6 +33,7 @@ internal class DefaultMultiPaneComponent( override val children: Value = children( source = navigation, + stateSerializer = NavigationState.serializer(), key = "children", initialState = ::NavigationState, navTransformer = { navState, event -> event(navState) }, @@ -76,24 +76,25 @@ internal class DefaultMultiPaneComponent( navigation.navigate { it.copy(isMultiPane = isMultiPane) } } - private sealed interface Config : Parcelable { - @Parcelize + @Serializable + private sealed interface Config { + @Serializable data object List : Config - @Parcelize + @Serializable data class Details(val articleId: Long) : Config } - @Parcelize + @Serializable private data class NavigationState( val isMultiPane: Boolean = false, val articleId: Long? = null, - ) : NavState, Parcelable { - override val children: List> - get() = - listOfNotNull( - SimpleChildNavState(Config.List, if (isMultiPane || (articleId == null)) Status.ACTIVE else Status.INACTIVE), - if (articleId != null) SimpleChildNavState(Config.Details(articleId), Status.ACTIVE) else null, - ) + ) : NavState { + override val children: List> by lazy { + listOfNotNull( + SimpleChildNavState(Config.List, if (isMultiPane || (articleId == null)) Status.ACTIVE else Status.INACTIVE), + if (articleId != null) SimpleChildNavState(Config.Details(articleId), Status.ACTIVE) else null, + ) + } } } diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/root/DefaultRootComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/root/DefaultRootComponent.kt index 93c5c1778..ac286bcd6 100644 --- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/root/DefaultRootComponent.kt +++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/root/DefaultRootComponent.kt @@ -8,8 +8,6 @@ import com.arkivanov.decompose.router.stack.bringToFront import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.webhistory.WebHistoryController import com.arkivanov.decompose.value.Value -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize import com.arkivanov.sample.shared.cards.DefaultCardsComponent import com.arkivanov.sample.shared.counters.DefaultCountersComponent import com.arkivanov.sample.shared.customnavigation.DefaultCustomNavigationComponent @@ -21,6 +19,7 @@ import com.arkivanov.sample.shared.root.RootComponent.Child.CountersChild import com.arkivanov.sample.shared.root.RootComponent.Child.CustomNavigationChild import com.arkivanov.sample.shared.root.RootComponent.Child.DynamicFeaturesChild import com.arkivanov.sample.shared.root.RootComponent.Child.MultiPaneChild +import kotlinx.serialization.Serializable @OptIn(ExperimentalDecomposeApi::class) class DefaultRootComponent( @@ -35,6 +34,7 @@ class DefaultRootComponent( private val stack = childStack( source = navigation, + serializer = Config.serializer(), initialStack = { getInitialStack(webHistoryPaths = webHistoryController?.historyPaths, deepLink = deepLink) }, childFactory = ::child, ) @@ -118,20 +118,21 @@ class DefaultRootComponent( } } - private sealed interface Config : Parcelable { - @Parcelize + @Serializable + private sealed interface Config { + @Serializable data object Counters : Config - @Parcelize + @Serializable data object Cards : Config - @Parcelize + @Serializable data object MultiPane : Config - @Parcelize + @Serializable data object DynamicFeatures : Config - @Parcelize + @Serializable data object CustomNavigation : Config }