Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.arkivanov.decompose.testutils

import com.arkivanov.decompose.Child
import com.arkivanov.decompose.value.Value
import com.arkivanov.essenty.statekeeper.StateKeeper
import com.arkivanov.essenty.statekeeper.StateKeeperDispatcher
import kotlin.reflect.KProperty
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer
import kotlin.reflect.KProperty

@PublishedApi
internal val json =
Expand All @@ -32,3 +33,5 @@ fun StateKeeperDispatcher.recreate(isConfigurationChange: Boolean = false): Stat
)

operator fun <T : Any> Value<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value

val List<Child<*, *>>.keys: List<String> get() = map { it.key }
26 changes: 14 additions & 12 deletions decompose/api/android/decompose.api
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,41 @@ public abstract interface class com/arkivanov/decompose/Cancellation {
public abstract class com/arkivanov/decompose/Child {
public abstract fun getConfiguration ()Ljava/lang/Object;
public abstract fun getInstance ()Ljava/lang/Object;
public abstract fun getKey ()Ljava/lang/Object;
public abstract fun getKey ()Ljava/lang/String;
}

public final class com/arkivanov/decompose/Child$Created : com/arkivanov/decompose/Child {
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/Object;
public final fun component2 ()Ljava/lang/Object;
public final fun component3 ()Ljava/lang/Object;
public final fun component3 ()Ljava/lang/String;
public final synthetic fun copy (Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child;
public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child$Created;
public static synthetic fun copy$default (Lcom/arkivanov/decompose/Child$Created;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lcom/arkivanov/decompose/Child$Created;
public final synthetic fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child$Created;
public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)Lcom/arkivanov/decompose/Child$Created;
public static synthetic fun copy$default (Lcom/arkivanov/decompose/Child$Created;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;ILjava/lang/Object;)Lcom/arkivanov/decompose/Child$Created;
public fun equals (Ljava/lang/Object;)Z
public fun getConfiguration ()Ljava/lang/Object;
public fun getInstance ()Ljava/lang/Object;
public fun getKey ()Ljava/lang/Object;
public fun getKey ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/arkivanov/decompose/Child$Destroyed : com/arkivanov/decompose/Child {
public fun <init> (Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/Object;
public final fun component2 ()Ljava/lang/Object;
public final fun component2 ()Ljava/lang/String;
public final synthetic fun copy (Ljava/lang/Object;)Lcom/arkivanov/decompose/Child;
public final fun copy (Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child$Destroyed;
public static synthetic fun copy$default (Lcom/arkivanov/decompose/Child$Destroyed;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lcom/arkivanov/decompose/Child$Destroyed;
public final synthetic fun copy (Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child$Destroyed;
public final fun copy (Ljava/lang/Object;Ljava/lang/String;)Lcom/arkivanov/decompose/Child$Destroyed;
public static synthetic fun copy$default (Lcom/arkivanov/decompose/Child$Destroyed;Ljava/lang/Object;Ljava/lang/String;ILjava/lang/Object;)Lcom/arkivanov/decompose/Child$Destroyed;
public fun equals (Ljava/lang/Object;)Z
public fun getConfiguration ()Ljava/lang/Object;
public synthetic fun getInstance ()Ljava/lang/Object;
public fun getInstance ()Ljava/lang/Void;
public fun getKey ()Ljava/lang/Object;
public fun getKey ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
Expand Down Expand Up @@ -567,7 +569,7 @@ public final class com/arkivanov/decompose/router/stack/ChildStack {
public fun <init> (Lcom/arkivanov/decompose/Child$Created;Ljava/util/List;)V
public synthetic fun <init> (Lcom/arkivanov/decompose/Child$Created;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)V
public final fun component1 ()Lcom/arkivanov/decompose/Child$Created;
public final fun component2 ()Ljava/util/List;
public final fun copy (Lcom/arkivanov/decompose/Child$Created;Ljava/util/List;)Lcom/arkivanov/decompose/router/stack/ChildStack;
Expand Down
22 changes: 12 additions & 10 deletions decompose/api/decompose.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ final class <#A: out kotlin/Any, #B: out kotlin/Any> com.arkivanov.decompose.rou

final class <#A: out kotlin/Any, #B: out kotlin/Any> com.arkivanov.decompose.router.stack/ChildStack { // com.arkivanov.decompose.router.stack/ChildStack|null[0]
constructor <init>(#A, #B) // com.arkivanov.decompose.router.stack/ChildStack.<init>|<init>(1:0;1:1){}[0]
constructor <init>(#A, #B, kotlin/Any) // com.arkivanov.decompose.router.stack/ChildStack.<init>|<init>(1:0;1:1;kotlin.Any){}[0]
constructor <init>(#A, #B, kotlin/String) // com.arkivanov.decompose.router.stack/ChildStack.<init>|<init>(1:0;1:1;kotlin.String){}[0]
constructor <init>(com.arkivanov.decompose/Child.Created<#A, #B>, kotlin.collections/List<com.arkivanov.decompose/Child.Created<#A, #B>> = ...) // com.arkivanov.decompose.router.stack/ChildStack.<init>|<init>(com.arkivanov.decompose.Child.Created<1:0,1:1>;kotlin.collections.List<com.arkivanov.decompose.Child.Created<1:0,1:1>>){}[0]

final val active // com.arkivanov.decompose.router.stack/ChildStack.active|{}active[0]
Expand Down Expand Up @@ -523,44 +523,46 @@ sealed class <#A: out kotlin/Any, #B: out kotlin/Any> com.arkivanov.decompose/Ch
abstract val instance // com.arkivanov.decompose/Child.instance|{}instance[0]
abstract fun <get-instance>(): #B? // com.arkivanov.decompose/Child.instance.<get-instance>|<get-instance>(){}[0]
abstract val key // com.arkivanov.decompose/Child.key|{}key[0]
abstract fun <get-key>(): kotlin/Any // com.arkivanov.decompose/Child.key.<get-key>|<get-key>(){}[0]
abstract fun <get-key>(): kotlin/String // com.arkivanov.decompose/Child.key.<get-key>|<get-key>(){}[0]

final class <#A1: out kotlin/Any, #B1: out kotlin/Any> Created : com.arkivanov.decompose/Child<#A1, #B1> { // com.arkivanov.decompose/Child.Created|null[0]
constructor <init>(#A1, #B1) // com.arkivanov.decompose/Child.Created.<init>|<init>(1:0;1:1){}[0]
constructor <init>(#A1, #B1, kotlin/Any) // com.arkivanov.decompose/Child.Created.<init>|<init>(1:0;1:1;kotlin.Any){}[0]
constructor <init>(#A1, #B1, kotlin/String) // com.arkivanov.decompose/Child.Created.<init>|<init>(1:0;1:1;kotlin.String){}[0]

final val configuration // com.arkivanov.decompose/Child.Created.configuration|{}configuration[0]
final fun <get-configuration>(): #A1 // com.arkivanov.decompose/Child.Created.configuration.<get-configuration>|<get-configuration>(){}[0]
final val instance // com.arkivanov.decompose/Child.Created.instance|{}instance[0]
final fun <get-instance>(): #B1 // com.arkivanov.decompose/Child.Created.instance.<get-instance>|<get-instance>(){}[0]
final val key // com.arkivanov.decompose/Child.Created.key|{}key[0]
final fun <get-key>(): kotlin/Any // com.arkivanov.decompose/Child.Created.key.<get-key>|<get-key>(){}[0]
final fun <get-key>(): kotlin/String // com.arkivanov.decompose/Child.Created.key.<get-key>|<get-key>(){}[0]

final fun component1(): #A1 // com.arkivanov.decompose/Child.Created.component1|component1(){}[0]
final fun component2(): #B1 // com.arkivanov.decompose/Child.Created.component2|component2(){}[0]
final fun component3(): kotlin/Any // com.arkivanov.decompose/Child.Created.component3|component3(){}[0]
final fun copy(#A1 = ..., #B1 = ..., kotlin/Any = ...): com.arkivanov.decompose/Child.Created<#A1, #B1> // com.arkivanov.decompose/Child.Created.copy|copy(1:0;1:1;kotlin.Any){}[0]
final fun component3(): kotlin/String // com.arkivanov.decompose/Child.Created.component3|component3(){}[0]
final fun copy(#A1 = ..., #B1 = ..., kotlin/String = ...): com.arkivanov.decompose/Child.Created<#A1, #B1> // com.arkivanov.decompose/Child.Created.copy|copy(1:0;1:1;kotlin.String){}[0]
final fun copy(#A1, #B1): com.arkivanov.decompose/Child<#A1, #B1> // com.arkivanov.decompose/Child.Created.copy|copy(1:0;1:1){}[0]
final fun copy(#A1, #B1, kotlin/Any): com.arkivanov.decompose/Child.Created<#A1, #B1> // com.arkivanov.decompose/Child.Created.copy|copy(1:0;1:1;kotlin.Any){}[0]
final fun equals(kotlin/Any?): kotlin/Boolean // com.arkivanov.decompose/Child.Created.equals|equals(kotlin.Any?){}[0]
final fun hashCode(): kotlin/Int // com.arkivanov.decompose/Child.Created.hashCode|hashCode(){}[0]
final fun toString(): kotlin/String // com.arkivanov.decompose/Child.Created.toString|toString(){}[0]
}

final class <#A1: out kotlin/Any> Destroyed : com.arkivanov.decompose/Child<#A1, kotlin/Nothing> { // com.arkivanov.decompose/Child.Destroyed|null[0]
constructor <init>(#A1) // com.arkivanov.decompose/Child.Destroyed.<init>|<init>(1:0){}[0]
constructor <init>(#A1, kotlin/Any) // com.arkivanov.decompose/Child.Destroyed.<init>|<init>(1:0;kotlin.Any){}[0]
constructor <init>(#A1, kotlin/String) // com.arkivanov.decompose/Child.Destroyed.<init>|<init>(1:0;kotlin.String){}[0]

final val configuration // com.arkivanov.decompose/Child.Destroyed.configuration|{}configuration[0]
final fun <get-configuration>(): #A1 // com.arkivanov.decompose/Child.Destroyed.configuration.<get-configuration>|<get-configuration>(){}[0]
final val instance // com.arkivanov.decompose/Child.Destroyed.instance|{}instance[0]
final fun <get-instance>(): kotlin/Nothing? // com.arkivanov.decompose/Child.Destroyed.instance.<get-instance>|<get-instance>(){}[0]
final val key // com.arkivanov.decompose/Child.Destroyed.key|{}key[0]
final fun <get-key>(): kotlin/Any // com.arkivanov.decompose/Child.Destroyed.key.<get-key>|<get-key>(){}[0]
final fun <get-key>(): kotlin/String // com.arkivanov.decompose/Child.Destroyed.key.<get-key>|<get-key>(){}[0]

final fun component1(): #A1 // com.arkivanov.decompose/Child.Destroyed.component1|component1(){}[0]
final fun component2(): kotlin/Any // com.arkivanov.decompose/Child.Destroyed.component2|component2(){}[0]
final fun copy(#A1 = ..., kotlin/Any = ...): com.arkivanov.decompose/Child.Destroyed<#A1> // com.arkivanov.decompose/Child.Destroyed.copy|copy(1:0;kotlin.Any){}[0]
final fun component2(): kotlin/String // com.arkivanov.decompose/Child.Destroyed.component2|component2(){}[0]
final fun copy(#A1 = ..., kotlin/String = ...): com.arkivanov.decompose/Child.Destroyed<#A1> // com.arkivanov.decompose/Child.Destroyed.copy|copy(1:0;kotlin.String){}[0]
final fun copy(#A1): com.arkivanov.decompose/Child<#A1, kotlin/Nothing> // com.arkivanov.decompose/Child.Destroyed.copy|copy(1:0){}[0]
final fun copy(#A1, kotlin/Any): com.arkivanov.decompose/Child.Destroyed<#A1> // com.arkivanov.decompose/Child.Destroyed.copy|copy(1:0;kotlin.Any){}[0]
final fun equals(kotlin/Any?): kotlin/Boolean // com.arkivanov.decompose/Child.Destroyed.equals|equals(kotlin.Any?){}[0]
final fun hashCode(): kotlin/Int // com.arkivanov.decompose/Child.Destroyed.hashCode|hashCode(){}[0]
final fun toString(): kotlin/String // com.arkivanov.decompose/Child.Destroyed.toString|toString(){}[0]
Expand Down
26 changes: 14 additions & 12 deletions decompose/api/jvm/decompose.api
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,41 @@ public abstract interface class com/arkivanov/decompose/Cancellation {
public abstract class com/arkivanov/decompose/Child {
public abstract fun getConfiguration ()Ljava/lang/Object;
public abstract fun getInstance ()Ljava/lang/Object;
public abstract fun getKey ()Ljava/lang/Object;
public abstract fun getKey ()Ljava/lang/String;
}

public final class com/arkivanov/decompose/Child$Created : com/arkivanov/decompose/Child {
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/Object;
public final fun component2 ()Ljava/lang/Object;
public final fun component3 ()Ljava/lang/Object;
public final fun component3 ()Ljava/lang/String;
public final synthetic fun copy (Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child;
public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child$Created;
public static synthetic fun copy$default (Lcom/arkivanov/decompose/Child$Created;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lcom/arkivanov/decompose/Child$Created;
public final synthetic fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child$Created;
public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)Lcom/arkivanov/decompose/Child$Created;
public static synthetic fun copy$default (Lcom/arkivanov/decompose/Child$Created;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;ILjava/lang/Object;)Lcom/arkivanov/decompose/Child$Created;
public fun equals (Ljava/lang/Object;)Z
public fun getConfiguration ()Ljava/lang/Object;
public fun getInstance ()Ljava/lang/Object;
public fun getKey ()Ljava/lang/Object;
public fun getKey ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/arkivanov/decompose/Child$Destroyed : com/arkivanov/decompose/Child {
public fun <init> (Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/Object;
public final fun component2 ()Ljava/lang/Object;
public final fun component2 ()Ljava/lang/String;
public final synthetic fun copy (Ljava/lang/Object;)Lcom/arkivanov/decompose/Child;
public final fun copy (Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child$Destroyed;
public static synthetic fun copy$default (Lcom/arkivanov/decompose/Child$Destroyed;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lcom/arkivanov/decompose/Child$Destroyed;
public final synthetic fun copy (Ljava/lang/Object;Ljava/lang/Object;)Lcom/arkivanov/decompose/Child$Destroyed;
public final fun copy (Ljava/lang/Object;Ljava/lang/String;)Lcom/arkivanov/decompose/Child$Destroyed;
public static synthetic fun copy$default (Lcom/arkivanov/decompose/Child$Destroyed;Ljava/lang/Object;Ljava/lang/String;ILjava/lang/Object;)Lcom/arkivanov/decompose/Child$Destroyed;
public fun equals (Ljava/lang/Object;)Z
public fun getConfiguration ()Ljava/lang/Object;
public synthetic fun getInstance ()Ljava/lang/Object;
public fun getInstance ()Ljava/lang/Void;
public fun getKey ()Ljava/lang/Object;
public fun getKey ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
Expand Down Expand Up @@ -547,7 +549,7 @@ public final class com/arkivanov/decompose/router/stack/ChildStack {
public fun <init> (Lcom/arkivanov/decompose/Child$Created;Ljava/util/List;)V
public synthetic fun <init> (Lcom/arkivanov/decompose/Child$Created;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)V
public final fun component1 ()Lcom/arkivanov/decompose/Child$Created;
public final fun component2 ()Ljava/util/List;
public final fun copy (Lcom/arkivanov/decompose/Child$Created;Ljava/util/List;)Lcom/arkivanov/decompose/router/stack/ChildStack;
Expand Down
40 changes: 29 additions & 11 deletions decompose/src/commonMain/kotlin/com/arkivanov/decompose/Child.kt
Original file line number Diff line number Diff line change
@@ -1,46 +1,64 @@
package com.arkivanov.decompose

/**
* A holder class for child [configuration], [instance] and [key].
*/
sealed class Child<out C : Any, out T : Any> {

/**
* A configuration object the child was originally created with.
*/
abstract val configuration: C

/**
* The actual child instance.
*/
abstract val instance: T?

@ExperimentalDecomposeApi
abstract val key: Any
/**
* A key of the child, unique within the navigation model managing the child.
*/
abstract val key: String

data class Created<out C : Any, out T : Any> @ExperimentalDecomposeApi constructor(
data class Created<out C : Any, out T : Any>(
override val configuration: C,
override val instance: T,

@property:ExperimentalDecomposeApi
override val key: Any,
override val key: String,
) : Child<C, T>() {
// TODO: Annotate with @VisibleForTesting in version 4.0
constructor(configuration: C, instance: T) : this(
configuration = configuration,
instance = instance,
key = configuration,
key = configuration.hashString(),
)

@Deprecated(message = "For binary compatibility", level = DeprecationLevel.HIDDEN)
fun copy(configuration: @UnsafeVariance C, instance: @UnsafeVariance T): Child<C, T> =
copy(configuration = configuration, instance = instance)

@Deprecated(message = "For binary compatibility", level = DeprecationLevel.HIDDEN)
fun copy(configuration: @UnsafeVariance C, instance: @UnsafeVariance T, key: Any): Created<C, T> =
copy(configuration = configuration, instance = instance, key = key.toString())
}

data class Destroyed<out C : Any> @ExperimentalDecomposeApi constructor(
override val configuration: C,

@property:ExperimentalDecomposeApi
override val key: Any,
override val key: String,
) : Child<C, Nothing>() {
// TODO: Annotate with @VisibleForTesting in version 4.0
constructor(configuration: C) : this(
configuration = configuration,
key = configuration,
key = configuration.hashString(),
)

override val instance: Nothing? = null

@Deprecated(message = "For binary compatibility", level = DeprecationLevel.HIDDEN)
fun copy(configuration: @UnsafeVariance C): Child<C, Nothing> =
copy(configuration = configuration)

@Deprecated(message = "For binary compatibility", level = DeprecationLevel.HIDDEN)
fun copy(configuration: @UnsafeVariance C, key: Any): Destroyed<C> =
copy(configuration = configuration, key = key.toString())
}
}
Loading
Loading