diff --git a/extensions-compose/api/android/extensions-compose.api b/extensions-compose/api/android/extensions-compose.api index 9bbfb6b80..8226acab3 100644 --- a/extensions-compose/api/android/extensions-compose.api +++ b/extensions-compose/api/android/extensions-compose.api @@ -48,11 +48,6 @@ public final class com/arkivanov/decompose/extensions/compose/pages/PagesScrollA public fun toString ()Ljava/lang/String; } -public final class com/arkivanov/decompose/extensions/compose/stack/ChildrenKt { - public static final fun Children (Lcom/arkivanov/decompose/router/stack/ChildStack;Landroidx/compose/ui/Modifier;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V - public static final fun Children (Lcom/arkivanov/decompose/value/Value;Landroidx/compose/ui/Modifier;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V -} - public final class com/arkivanov/decompose/extensions/compose/stack/animation/Direction : java/lang/Enum { public static final field ENTER_BACK Lcom/arkivanov/decompose/extensions/compose/stack/animation/Direction; public static final field ENTER_FRONT Lcom/arkivanov/decompose/extensions/compose/stack/animation/Direction; @@ -70,52 +65,6 @@ public final class com/arkivanov/decompose/extensions/compose/stack/animation/Di public static final fun isFront (Lcom/arkivanov/decompose/extensions/compose/stack/animation/Direction;)Z } -public final class com/arkivanov/decompose/extensions/compose/stack/animation/FadeKt { - public static final fun fade (Landroidx/compose/animation/core/FiniteAnimationSpec;F)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static synthetic fun fade$default (Landroidx/compose/animation/core/FiniteAnimationSpec;FILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/ScaleKt { - public static final fun scale (Landroidx/compose/animation/core/FiniteAnimationSpec;FF)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static synthetic fun scale$default (Landroidx/compose/animation/core/FiniteAnimationSpec;FFILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/SlideKt { - public static final fun slide (Landroidx/compose/animation/core/FiniteAnimationSpec;Landroidx/compose/foundation/gestures/Orientation;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static synthetic fun slide$default (Landroidx/compose/animation/core/FiniteAnimationSpec;Landroidx/compose/foundation/gestures/Orientation;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; -} - -public abstract interface class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation { - public abstract fun invoke (Lcom/arkivanov/decompose/router/stack/ChildStack;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationKt { - public static final fun stackAnimation (Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator;Z)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static final fun stackAnimation (ZLkotlin/jvm/functions/Function1;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static final fun stackAnimation (ZLkotlin/jvm/functions/Function3;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static synthetic fun stackAnimation$default (Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator;ZILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static synthetic fun stackAnimation$default (ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static synthetic fun stackAnimation$default (ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; -} - -public abstract interface class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationProvider { - public abstract fun provide ()Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationProviderKt { - public static final fun getLocalStackAnimationProvider ()Landroidx/compose/runtime/ProvidableCompositionLocal; -} - -public abstract interface class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator { - public abstract fun invoke (Lcom/arkivanov/decompose/extensions/compose/stack/animation/Direction;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimatorKt { - public static final fun plus (Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static final fun stackAnimator (Landroidx/compose/animation/core/FiniteAnimationSpec;Lkotlin/jvm/functions/Function5;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static synthetic fun stackAnimator$default (Landroidx/compose/animation/core/FiniteAnimationSpec;Lkotlin/jvm/functions/Function5;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; -} - public final class com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/AndroidPredictiveBackAnimatableKt { public static final fun androidPredictiveBackAnimatableV1 (Lcom/arkivanov/essenty/backhandler/BackEvent;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimatable; public static synthetic fun androidPredictiveBackAnimatableV1$default (Lcom/arkivanov/essenty/backhandler/BackEvent;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimatable; @@ -140,8 +89,3 @@ public final class com/arkivanov/decompose/extensions/compose/stack/animation/pr public static final fun predictiveBackAnimatable (Lcom/arkivanov/essenty/backhandler/BackEvent;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimatable; } -public final class com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimationKt { - public static final fun predictiveBackAnimation (Lcom/arkivanov/essenty/backhandler/BackHandler;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static synthetic fun predictiveBackAnimation$default (Lcom/arkivanov/essenty/backhandler/BackHandler;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; -} - diff --git a/extensions-compose/api/extensions-compose.klib.api b/extensions-compose/api/extensions-compose.klib.api index 6f2e0e6c4..29b65af11 100644 --- a/extensions-compose/api/extensions-compose.klib.api +++ b/extensions-compose/api/extensions-compose.klib.api @@ -19,14 +19,6 @@ final enum class com.arkivanov.decompose.extensions.compose.stack.animation/Dire final fun values(): kotlin/Array // com.arkivanov.decompose.extensions.compose.stack.animation/Direction.values|values#static(){}[0] } -abstract fun interface <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation { // com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation|null[0] - abstract fun invoke(com.arkivanov.decompose.router.stack/ChildStack<#A, #B>, androidx.compose.ui/Modifier, kotlin/Function3, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int) // com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation.invoke|invoke(com.arkivanov.decompose.router.stack.ChildStack<1:0,1:1>;androidx.compose.ui.Modifier;kotlin.Function3,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int){}[0] -} - -abstract fun interface com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator { // com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator|null[0] - abstract fun invoke(com.arkivanov.decompose.extensions.compose.stack.animation/Direction, kotlin/Boolean, kotlin/Function0, kotlin/Function3, androidx.compose.runtime/Composer?, kotlin/Int) // com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator.invoke|invoke(com.arkivanov.decompose.extensions.compose.stack.animation.Direction;kotlin.Boolean;kotlin.Function0;kotlin.Function3;androidx.compose.runtime.Composer?;kotlin.Int){}[0] -} - abstract interface com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/PredictiveBackAnimatable { // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/PredictiveBackAnimatable|null[0] abstract val enterModifier // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/PredictiveBackAnimatable.enterModifier|{}enterModifier[0] abstract fun (): androidx.compose.ui/Modifier // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/PredictiveBackAnimatable.enterModifier.|(){}[0] @@ -38,10 +30,6 @@ abstract interface com.arkivanov.decompose.extensions.compose.stack.animation.pr abstract suspend fun finish() // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/PredictiveBackAnimatable.finish|finish(){}[0] } -abstract interface com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimationProvider { // com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimationProvider|null[0] - abstract fun <#A1: kotlin/Any, #B1: kotlin/Any> provide(): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation<#A1, #B1>? // com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimationProvider.provide|provide(){0§;1§}[0] -} - sealed interface com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation { // com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation|null[0] final class Custom : com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation { // com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation.Custom|null[0] constructor (androidx.compose.animation.core/AnimationSpec) // com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation.Custom.|(androidx.compose.animation.core.AnimationSpec){}[0] @@ -71,13 +59,6 @@ final val com.arkivanov.decompose.extensions.compose.stack.animation.predictiveb final val com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_DefaultPredictiveBackAnimatable$stableprop // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_DefaultPredictiveBackAnimatable$stableprop|#static{}com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_DefaultPredictiveBackAnimatable$stableprop[0] final val com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorner$stableprop // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorner$stableprop|#static{}com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorner$stableprop[0] final val com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorners$stableprop // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorners$stableprop|#static{}com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorners$stableprop[0] -final val com.arkivanov.decompose.extensions.compose.stack.animation/LocalStackAnimationProvider // com.arkivanov.decompose.extensions.compose.stack.animation/LocalStackAnimationProvider|{}LocalStackAnimationProvider[0] - final fun (): androidx.compose.runtime/ProvidableCompositionLocal // com.arkivanov.decompose.extensions.compose.stack.animation/LocalStackAnimationProvider.|(){}[0] -final val com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_AbstractStackAnimation$stableprop // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_AbstractStackAnimation$stableprop|#static{}com_arkivanov_decompose_extensions_compose_stack_animation_AbstractStackAnimation$stableprop[0] -final val com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_DefaultStackAnimator$stableprop // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_DefaultStackAnimator$stableprop|#static{}com_arkivanov_decompose_extensions_compose_stack_animation_DefaultStackAnimator$stableprop[0] -final val com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_EmptyStackAnimator$stableprop // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_EmptyStackAnimator$stableprop|#static{}com_arkivanov_decompose_extensions_compose_stack_animation_EmptyStackAnimator$stableprop[0] -final val com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_MovableStackAnimation$stableprop // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_MovableStackAnimation$stableprop|#static{}com_arkivanov_decompose_extensions_compose_stack_animation_MovableStackAnimation$stableprop[0] -final val com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_SimpleStackAnimation$stableprop // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_SimpleStackAnimation$stableprop|#static{}com_arkivanov_decompose_extensions_compose_stack_animation_SimpleStackAnimation$stableprop[0] final val com.arkivanov.decompose.extensions.compose.stack.animation/isBack // com.arkivanov.decompose.extensions.compose.stack.animation/isBack|@com.arkivanov.decompose.extensions.compose.stack.animation.Direction{}isBack[0] final fun (com.arkivanov.decompose.extensions.compose.stack.animation/Direction).(): kotlin/Boolean // com.arkivanov.decompose.extensions.compose.stack.animation/isBack.|@com.arkivanov.decompose.extensions.compose.stack.animation.Direction(){}[0] final val com.arkivanov.decompose.extensions.compose.stack.animation/isEnter // com.arkivanov.decompose.extensions.compose.stack.animation/isEnter|@com.arkivanov.decompose.extensions.compose.stack.animation.Direction{}isEnter[0] @@ -87,17 +68,10 @@ final val com.arkivanov.decompose.extensions.compose.stack.animation/isExit // c final val com.arkivanov.decompose.extensions.compose.stack.animation/isFront // com.arkivanov.decompose.extensions.compose.stack.animation/isFront|@com.arkivanov.decompose.extensions.compose.stack.animation.Direction{}isFront[0] final fun (com.arkivanov.decompose.extensions.compose.stack.animation/Direction).(): kotlin/Boolean // com.arkivanov.decompose.extensions.compose.stack.animation/isFront.|@com.arkivanov.decompose.extensions.compose.stack.animation.Direction(){}[0] -final fun (com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator).com.arkivanov.decompose.extensions.compose.stack.animation/plus(com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator // com.arkivanov.decompose.extensions.compose.stack.animation/plus|plus@com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimator(com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimator){}[0] final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.pages/ChildPages(com.arkivanov.decompose.router.pages/ChildPages<#A, #B>, kotlin/Function1, androidx.compose.ui/Modifier?, com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation?, kotlin/Function6, kotlin/Function4, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function1, kotlin/Any>?, kotlin/Function5, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.arkivanov.decompose.extensions.compose.pages/ChildPages|ChildPages(com.arkivanov.decompose.router.pages.ChildPages<0:0,0:1>;kotlin.Function1;androidx.compose.ui.Modifier?;com.arkivanov.decompose.extensions.compose.pages.PagesScrollAnimation?;kotlin.Function6,kotlin.Function4,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function1,kotlin.Any>?;kotlin.Function5;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§;1§}[0] final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.pages/ChildPages(com.arkivanov.decompose.router.pages/ChildPages<#A, #B>, kotlin/Function1, androidx.compose.ui/Modifier?, com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation?, kotlin/Function6, kotlin/Function4, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function1, kotlin/Any>?, kotlin/Function6, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.arkivanov.decompose.extensions.compose.pages/ChildPages|ChildPages(com.arkivanov.decompose.router.pages.ChildPages<0:0,0:1>;kotlin.Function1;androidx.compose.ui.Modifier?;com.arkivanov.decompose.extensions.compose.pages.PagesScrollAnimation?;kotlin.Function6,kotlin.Function4,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function1,kotlin.Any>?;kotlin.Function6;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§;1§}[0] final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.pages/ChildPages(com.arkivanov.decompose.value/Value>, kotlin/Function1, androidx.compose.ui/Modifier?, com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation?, kotlin/Function6, kotlin/Function4, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function1, kotlin/Any>?, kotlin/Function5, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.arkivanov.decompose.extensions.compose.pages/ChildPages|ChildPages(com.arkivanov.decompose.value.Value>;kotlin.Function1;androidx.compose.ui.Modifier?;com.arkivanov.decompose.extensions.compose.pages.PagesScrollAnimation?;kotlin.Function6,kotlin.Function4,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function1,kotlin.Any>?;kotlin.Function5;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§;1§}[0] final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.pages/ChildPages(com.arkivanov.decompose.value/Value>, kotlin/Function1, androidx.compose.ui/Modifier?, com.arkivanov.decompose.extensions.compose.pages/PagesScrollAnimation?, kotlin/Function6, kotlin/Function4, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function1, kotlin/Any>?, kotlin/Function6, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.arkivanov.decompose.extensions.compose.pages/ChildPages|ChildPages(com.arkivanov.decompose.value.Value>;kotlin.Function1;androidx.compose.ui.Modifier?;com.arkivanov.decompose.extensions.compose.pages.PagesScrollAnimation?;kotlin.Function6,kotlin.Function4,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function1,kotlin.Any>?;kotlin.Function6;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§;1§}[0] -final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/predictiveBackAnimation(com.arkivanov.essenty.backhandler/BackHandler, com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation<#A, #B>? = ..., kotlin/Function3, com.arkivanov.decompose/Child.Created<#A, #B>, com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/PredictiveBackAnimatable> = ..., kotlin/Function0): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation<#A, #B> // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/predictiveBackAnimation|predictiveBackAnimation(com.arkivanov.essenty.backhandler.BackHandler;com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimation<0:0,0:1>?;kotlin.Function3,com.arkivanov.decompose.Child.Created<0:0,0:1>,com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback.PredictiveBackAnimatable>;kotlin.Function0){0§;1§}[0] -final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.stack.animation/stackAnimation(com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator = ..., kotlin/Boolean = ...): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation<#A, #B> // com.arkivanov.decompose.extensions.compose.stack.animation/stackAnimation|stackAnimation(com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimator;kotlin.Boolean){0§;1§}[0] -final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.stack.animation/stackAnimation(kotlin/Boolean = ..., kotlin/Function1, com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator?>): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation<#A, #B> // com.arkivanov.decompose.extensions.compose.stack.animation/stackAnimation|stackAnimation(kotlin.Boolean;kotlin.Function1,com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimator?>){0§;1§}[0] -final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.stack.animation/stackAnimation(kotlin/Boolean = ..., kotlin/Function3, com.arkivanov.decompose/Child.Created<#A, #B>, com.arkivanov.decompose.extensions.compose.stack.animation/Direction, com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator?>): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation<#A, #B> // com.arkivanov.decompose.extensions.compose.stack.animation/stackAnimation|stackAnimation(kotlin.Boolean;kotlin.Function3,com.arkivanov.decompose.Child.Created<0:0,0:1>,com.arkivanov.decompose.extensions.compose.stack.animation.Direction,com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimator?>){0§;1§}[0] -final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.stack/Children(com.arkivanov.decompose.router.stack/ChildStack<#A, #B>, androidx.compose.ui/Modifier?, com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation<#A, #B>?, kotlin/Function3, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.arkivanov.decompose.extensions.compose.stack/Children|Children(com.arkivanov.decompose.router.stack.ChildStack<0:0,0:1>;androidx.compose.ui.Modifier?;com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimation<0:0,0:1>?;kotlin.Function3,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§;1§}[0] -final fun <#A: kotlin/Any, #B: kotlin/Any> com.arkivanov.decompose.extensions.compose.stack/Children(com.arkivanov.decompose.value/Value>, androidx.compose.ui/Modifier?, com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimation<#A, #B>?, kotlin/Function3, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.arkivanov.decompose.extensions.compose.stack/Children|Children(com.arkivanov.decompose.value.Value>;androidx.compose.ui.Modifier?;com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimation<0:0,0:1>?;kotlin.Function3,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§;1§}[0] final fun <#A: kotlin/Any> (com.arkivanov.decompose.value/Value<#A>).com.arkivanov.decompose.extensions.compose/subscribeAsState(androidx.compose.runtime/SnapshotMutationPolicy<#A>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.runtime/State<#A> // com.arkivanov.decompose.extensions.compose/subscribeAsState|subscribeAsState@com.arkivanov.decompose.value.Value<0:0>(androidx.compose.runtime.SnapshotMutationPolicy<0:0>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§}[0] final fun <#A: kotlin/Any> com.arkivanov.decompose.extensions.compose.lazyitems/ChildItemsLifecycleController(com.arkivanov.decompose.router.items/LazyChildItems<#A, *>, androidx.compose.foundation.lazy.grid/LazyGridState, kotlin/Function1, kotlin/Int, kotlin/Int, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.arkivanov.decompose.extensions.compose.lazyitems/ChildItemsLifecycleController|ChildItemsLifecycleController(com.arkivanov.decompose.router.items.LazyChildItems<0:0,*>;androidx.compose.foundation.lazy.grid.LazyGridState;kotlin.Function1;kotlin.Int;kotlin.Int;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§}[0] final fun <#A: kotlin/Any> com.arkivanov.decompose.extensions.compose.lazyitems/ChildItemsLifecycleController(com.arkivanov.decompose.router.items/LazyChildItems<#A, *>, androidx.compose.foundation.lazy/LazyListState, kotlin/Function1, kotlin/Int, kotlin/Int, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.arkivanov.decompose.extensions.compose.lazyitems/ChildItemsLifecycleController|ChildItemsLifecycleController(com.arkivanov.decompose.router.items.LazyChildItems<0:0,*>;androidx.compose.foundation.lazy.LazyListState;kotlin.Function1;kotlin.Int;kotlin.Int;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§}[0] @@ -117,12 +91,3 @@ final fun com.arkivanov.decompose.extensions.compose.stack.animation.predictiveb final fun com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorners$stableprop_getter(): kotlin/Int // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorners$stableprop_getter|com_arkivanov_decompose_extensions_compose_stack_animation_predictiveback_LayoutCorners$stableprop_getter(){}[0] final fun com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/materialPredictiveBackAnimatable(com.arkivanov.essenty.backhandler/BackEvent, kotlin/Function2? = ...): com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/PredictiveBackAnimatable // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/materialPredictiveBackAnimatable|materialPredictiveBackAnimatable(com.arkivanov.essenty.backhandler.BackEvent;kotlin.Function2?){}[0] final fun com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/predictiveBackAnimatable(com.arkivanov.essenty.backhandler/BackEvent, kotlin/Function2, kotlin/Function2): com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/PredictiveBackAnimatable // com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback/predictiveBackAnimatable|predictiveBackAnimatable(com.arkivanov.essenty.backhandler.BackEvent;kotlin.Function2;kotlin.Function2){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_AbstractStackAnimation$stableprop_getter(): kotlin/Int // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_AbstractStackAnimation$stableprop_getter|com_arkivanov_decompose_extensions_compose_stack_animation_AbstractStackAnimation$stableprop_getter(){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_DefaultStackAnimator$stableprop_getter(): kotlin/Int // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_DefaultStackAnimator$stableprop_getter|com_arkivanov_decompose_extensions_compose_stack_animation_DefaultStackAnimator$stableprop_getter(){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_EmptyStackAnimator$stableprop_getter(): kotlin/Int // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_EmptyStackAnimator$stableprop_getter|com_arkivanov_decompose_extensions_compose_stack_animation_EmptyStackAnimator$stableprop_getter(){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_MovableStackAnimation$stableprop_getter(): kotlin/Int // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_MovableStackAnimation$stableprop_getter|com_arkivanov_decompose_extensions_compose_stack_animation_MovableStackAnimation$stableprop_getter(){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_SimpleStackAnimation$stableprop_getter(): kotlin/Int // com.arkivanov.decompose.extensions.compose.stack.animation/com_arkivanov_decompose_extensions_compose_stack_animation_SimpleStackAnimation$stableprop_getter|com_arkivanov_decompose_extensions_compose_stack_animation_SimpleStackAnimation$stableprop_getter(){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/fade(androidx.compose.animation.core/FiniteAnimationSpec = ..., kotlin/Float = ...): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator // com.arkivanov.decompose.extensions.compose.stack.animation/fade|fade(androidx.compose.animation.core.FiniteAnimationSpec;kotlin.Float){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/scale(androidx.compose.animation.core/FiniteAnimationSpec = ..., kotlin/Float = ..., kotlin/Float = ...): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator // com.arkivanov.decompose.extensions.compose.stack.animation/scale|scale(androidx.compose.animation.core.FiniteAnimationSpec;kotlin.Float;kotlin.Float){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/slide(androidx.compose.animation.core/FiniteAnimationSpec = ..., androidx.compose.foundation.gestures/Orientation = ...): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator // com.arkivanov.decompose.extensions.compose.stack.animation/slide|slide(androidx.compose.animation.core.FiniteAnimationSpec;androidx.compose.foundation.gestures.Orientation){}[0] -final fun com.arkivanov.decompose.extensions.compose.stack.animation/stackAnimator(androidx.compose.animation.core/FiniteAnimationSpec = ..., kotlin/Function5, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>): com.arkivanov.decompose.extensions.compose.stack.animation/StackAnimator // com.arkivanov.decompose.extensions.compose.stack.animation/stackAnimator|stackAnimator(androidx.compose.animation.core.FiniteAnimationSpec;kotlin.Function5,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>){}[0] diff --git a/extensions-compose/api/jvm/extensions-compose.api b/extensions-compose/api/jvm/extensions-compose.api index ae717dee0..1df816e6e 100644 --- a/extensions-compose/api/jvm/extensions-compose.api +++ b/extensions-compose/api/jvm/extensions-compose.api @@ -52,11 +52,6 @@ public final class com/arkivanov/decompose/extensions/compose/pages/PagesScrollA public fun toString ()Ljava/lang/String; } -public final class com/arkivanov/decompose/extensions/compose/stack/ChildrenKt { - public static final fun Children (Lcom/arkivanov/decompose/router/stack/ChildStack;Landroidx/compose/ui/Modifier;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V - public static final fun Children (Lcom/arkivanov/decompose/value/Value;Landroidx/compose/ui/Modifier;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V -} - public final class com/arkivanov/decompose/extensions/compose/stack/animation/Direction : java/lang/Enum { public static final field ENTER_BACK Lcom/arkivanov/decompose/extensions/compose/stack/animation/Direction; public static final field ENTER_FRONT Lcom/arkivanov/decompose/extensions/compose/stack/animation/Direction; @@ -74,52 +69,6 @@ public final class com/arkivanov/decompose/extensions/compose/stack/animation/Di public static final fun isFront (Lcom/arkivanov/decompose/extensions/compose/stack/animation/Direction;)Z } -public final class com/arkivanov/decompose/extensions/compose/stack/animation/FadeKt { - public static final fun fade (Landroidx/compose/animation/core/FiniteAnimationSpec;F)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static synthetic fun fade$default (Landroidx/compose/animation/core/FiniteAnimationSpec;FILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/ScaleKt { - public static final fun scale (Landroidx/compose/animation/core/FiniteAnimationSpec;FF)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static synthetic fun scale$default (Landroidx/compose/animation/core/FiniteAnimationSpec;FFILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/SlideKt { - public static final fun slide (Landroidx/compose/animation/core/FiniteAnimationSpec;Landroidx/compose/foundation/gestures/Orientation;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static synthetic fun slide$default (Landroidx/compose/animation/core/FiniteAnimationSpec;Landroidx/compose/foundation/gestures/Orientation;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; -} - -public abstract interface class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation { - public abstract fun invoke (Lcom/arkivanov/decompose/router/stack/ChildStack;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationKt { - public static final fun stackAnimation (Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator;Z)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static final fun stackAnimation (ZLkotlin/jvm/functions/Function1;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static final fun stackAnimation (ZLkotlin/jvm/functions/Function3;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static synthetic fun stackAnimation$default (Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator;ZILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static synthetic fun stackAnimation$default (ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static synthetic fun stackAnimation$default (ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; -} - -public abstract interface class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationProvider { - public abstract fun provide ()Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationProviderKt { - public static final fun getLocalStackAnimationProvider ()Landroidx/compose/runtime/ProvidableCompositionLocal; -} - -public abstract interface class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator { - public abstract fun invoke (Lcom/arkivanov/decompose/extensions/compose/stack/animation/Direction;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V -} - -public final class com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimatorKt { - public static final fun plus (Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static final fun stackAnimator (Landroidx/compose/animation/core/FiniteAnimationSpec;Lkotlin/jvm/functions/Function5;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; - public static synthetic fun stackAnimator$default (Landroidx/compose/animation/core/FiniteAnimationSpec;Lkotlin/jvm/functions/Function5;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator; -} - public final class com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/AndroidPredictiveBackAnimatableKt { public static final fun androidPredictiveBackAnimatableV1 (Lcom/arkivanov/essenty/backhandler/BackEvent;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimatable; public static synthetic fun androidPredictiveBackAnimatableV1$default (Lcom/arkivanov/essenty/backhandler/BackEvent;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimatable; @@ -144,11 +93,6 @@ public final class com/arkivanov/decompose/extensions/compose/stack/animation/pr public static final fun predictiveBackAnimatable (Lcom/arkivanov/essenty/backhandler/BackEvent;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimatable; } -public final class com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimationKt { - public static final fun predictiveBackAnimation (Lcom/arkivanov/essenty/backhandler/BackHandler;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; - public static synthetic fun predictiveBackAnimation$default (Lcom/arkivanov/essenty/backhandler/BackHandler;Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation; -} - public final class com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackGestureIconKt { public static final fun PredictiveBackGestureIcon-eaDK9VM (Landroidx/compose/ui/graphics/vector/ImageVector;FJJLandroidx/compose/runtime/Composer;II)V } diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/Children.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/Children.kt deleted file mode 100644 index ba8d484c1..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/Children.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.SaveableStateHolder -import androidx.compose.runtime.saveable.rememberSaveableStateHolder -import androidx.compose.ui.Modifier -import com.arkivanov.decompose.Child -import com.arkivanov.decompose.extensions.compose.stack.animation.LocalStackAnimationProvider -import com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimation -import com.arkivanov.decompose.extensions.compose.stack.animation.emptyStackAnimation -import com.arkivanov.decompose.extensions.compose.subscribeAsState -import com.arkivanov.decompose.router.stack.ChildStack -import com.arkivanov.decompose.value.Value - -@Composable -fun Children( - stack: ChildStack, - modifier: Modifier = Modifier, - animation: StackAnimation? = null, - content: @Composable (child: Child.Created) -> Unit, -) { - val holder = rememberSaveableStateHolder() - - holder.retainStates(stack.getKeys()) - - val animationProvider = LocalStackAnimationProvider.current - val anim = animation ?: remember(animationProvider, animationProvider::provide) ?: emptyStackAnimation() - - anim(stack = stack, modifier = modifier) { child -> - holder.SaveableStateProvider(child.key) { - content(child) - } - } -} - -@Composable -fun Children( - stack: Value>, - modifier: Modifier = Modifier, - animation: StackAnimation? = null, - content: @Composable (child: Child.Created) -> Unit, -) { - val state = stack.subscribeAsState() - - Children( - stack = state.value, - modifier = modifier, - animation = animation, - content = content - ) -} - -private fun ChildStack<*, *>.getKeys(): Set = - items.mapTo(HashSet(), Child<*, *>::key) - -@Composable -private fun SaveableStateHolder.retainStates(currentKeys: Set) { - val keys = remember(this) { Keys(currentKeys) } - - DisposableEffect(this, currentKeys) { - keys.set.forEach { - if (it !in currentKeys) { - removeState(it) - } - } - - keys.set = currentKeys - - onDispose {} - } -} - -private class Keys( - var set: Set, -) diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/AbstractStackAnimation.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/AbstractStackAnimation.kt deleted file mode 100644 index ae890c8dd..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/AbstractStackAnimation.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.foundation.layout.Box -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.key -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import com.arkivanov.decompose.Child -import com.arkivanov.decompose.extensions.compose.utils.InputConsumingOverlay -import com.arkivanov.decompose.router.stack.ChildStack - -internal abstract class AbstractStackAnimation( - private val disableInputDuringAnimation: Boolean, -) : StackAnimation { - - @Composable - protected abstract fun Child( - item: AnimationItem, - onFinished: () -> Unit, - content: @Composable (child: Child.Created) -> Unit, - ) - - @Composable - override operator fun invoke(stack: ChildStack, modifier: Modifier, content: @Composable (child: Child.Created) -> Unit) { - var currentStack by remember { mutableStateOf(stack) } - var items by remember { mutableStateOf(getAnimationItems(newStack = currentStack, oldStack = null)) } - var nextItems: Map>? by remember { mutableStateOf(null) } - - if (stack.active.key != currentStack.active.key || stack.active.instance != currentStack.active.instance) { - val oldStack = currentStack - currentStack = stack - - val newItems = getAnimationItems(newStack = currentStack, oldStack = oldStack) - if (items.size == 1) { - val oldLastKey = items.keys.last() - val (newLastKey, newLastItem) = newItems.entries.last() - items = if ((newLastKey != oldLastKey) || newLastItem.direction.isExit) newItems else mapOf(newLastKey to newLastItem) - nextItems = null - } else { - nextItems = newItems - } - } - - Box(modifier = modifier) { - items.forEach { (key, item) -> - key(key) { - Child( - item = item, - onFinished = { - if (item.direction.isExit) { - items -= key - } else { - items += (key to item.copy(otherChild = null)) - } - }, - content = content, - ) - - if (item.direction.isExit) { - DisposableEffect(Unit) { - onDispose { - nextItems?.also { items = it } - nextItems = null - } - } - } - } - } - - // A workaround until https://issuetracker.google.com/issues/214231672. - // Normally only the exiting child should be disabled. - if (disableInputDuringAnimation && ((items.size > 1) || (nextItems != null))) { - InputConsumingOverlay(modifier = Modifier.matchParentSize()) - } - } - } - - private fun getAnimationItems(newStack: ChildStack, oldStack: ChildStack?): Map> = - when { - (oldStack == null) || (newStack.active.key == oldStack.active.key) -> - listOf(AnimationItem(child = newStack.active, direction = Direction.ENTER_FRONT, isInitial = true)) - - (newStack.size < oldStack.size) && (newStack.active.key in oldStack.backStack) -> - listOf( - AnimationItem(child = newStack.active, direction = Direction.ENTER_BACK, otherChild = oldStack.active), - AnimationItem(child = oldStack.active, direction = Direction.EXIT_FRONT, otherChild = newStack.active), - ) - - else -> - listOf( - AnimationItem(child = oldStack.active, direction = Direction.EXIT_BACK, otherChild = newStack.active), - AnimationItem(child = newStack.active, direction = Direction.ENTER_FRONT, otherChild = oldStack.active), - ) - }.associateBy { it.child.key } - - private val ChildStack<*, *>.size: Int - get() = items.size - - private operator fun Iterable>.contains(key: Any): Boolean = - any { it.key == key } - - protected data class AnimationItem( - val child: Child.Created, - val direction: Direction, - val isInitial: Boolean = false, - val otherChild: Child.Created? = null, - ) -} diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/DefaultStackAnimator.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/DefaultStackAnimator.kt deleted file mode 100644 index 960939cf5..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/DefaultStackAnimator.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.animation.core.AnimationState -import androidx.compose.animation.core.FiniteAnimationSpec -import androidx.compose.animation.core.animateTo -import androidx.compose.animation.core.isFinished -import androidx.compose.animation.core.tween -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberUpdatedState -import androidx.compose.ui.Modifier - -internal class DefaultStackAnimator( - private val animationSpec: FiniteAnimationSpec = tween(), - private val frame: @Composable (factor: Float, direction: Direction, content: @Composable (Modifier) -> Unit) -> Unit -) : StackAnimator { - - @Composable - override operator fun invoke( - direction: Direction, - isInitial: Boolean, - onFinished: () -> Unit, - content: @Composable (Modifier) -> Unit, - ) { - val onFinishedRef by rememberUpdatedState(onFinished) - val animationState = remember(direction, isInitial) { AnimationState(initialValue = if (isInitial) 0F else 1F) } - - LaunchedEffect(animationState) { - animationState.animateTo( - targetValue = 0F, - animationSpec = animationSpec, - sequentialAnimation = !animationState.isFinished, - ) - - onFinishedRef() - } - - val factor = - when (direction) { - Direction.ENTER_FRONT -> animationState.value - Direction.EXIT_FRONT -> 1F - animationState.value - Direction.ENTER_BACK -> -animationState.value - Direction.EXIT_BACK -> animationState.value - 1F - } - - frame(factor, direction, content) - } -} diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/EmptyStackAnimation.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/EmptyStackAnimation.kt deleted file mode 100644 index 22c2be508..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/EmptyStackAnimation.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.foundation.layout.Box -import androidx.compose.runtime.Composable -import androidx.compose.runtime.compositionLocalOf -import androidx.compose.ui.Modifier -import com.arkivanov.decompose.Child -import com.arkivanov.decompose.router.stack.ChildStack - -internal fun emptyStackAnimation(): StackAnimation = - EmptyStackAnimation() - -/* - * Can't be anonymous. See: - * https://github.com/JetBrains/compose-jb/issues/2688 - * https://github.com/JetBrains/compose-jb/issues/2612 - */ -private class EmptyStackAnimation : StackAnimation { - - @Composable - override fun invoke( - stack: ChildStack, - modifier: Modifier, - content: @Composable (child: Child.Created) -> Unit, - ) { - Box(modifier = modifier) { - content(stack.active) - } - } -} diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/EmptyStackAnimator.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/EmptyStackAnimator.kt deleted file mode 100644 index 2e4a3d178..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/EmptyStackAnimator.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.ui.Modifier - -internal object EmptyStackAnimator : StackAnimator { - - @Composable - override fun invoke( - direction: Direction, - isInitial: Boolean, - onFinished: () -> Unit, - content: @Composable (Modifier) -> Unit, - ) { - content(Modifier) - - DisposableEffect(direction, isInitial) { - onFinished() - onDispose {} - } - } -} diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Fade.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Fade.kt deleted file mode 100644 index e9d4b5e38..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Fade.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.animation.core.FiniteAnimationSpec -import androidx.compose.animation.core.tween -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import kotlin.math.abs - -/** - * A simple fading animation. Appearing children's `alpha` is animated from [minAlpha] to 1.0. - * Disappearing children's `alpha` is animated from 1.0 to [minAlpha]. - */ -fun fade( - animationSpec: FiniteAnimationSpec = tween(), - minAlpha: Float = 0F, -): StackAnimator = - stackAnimator(animationSpec = animationSpec) { factor, _, content -> - content(Modifier.alpha(getFadeAlpha(factor = factor, minAlpha = minAlpha))) - } - -internal fun getFadeAlpha(factor: Float, minAlpha: Float): Float = - (1F - abs(factor) * (1F - minAlpha)).coerceIn(minimumValue = 0F, maximumValue = 1F) diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/MovableStackAnimation.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/MovableStackAnimation.kt deleted file mode 100644 index e7213cb47..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/MovableStackAnimation.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.foundation.layout.Box -import androidx.compose.runtime.Composable -import androidx.compose.runtime.movableContentOf -import androidx.compose.runtime.remember -import com.arkivanov.decompose.Child - -internal class MovableStackAnimation( - disableInputDuringAnimation: Boolean, - private val selector: (child: Child.Created, otherChild: Child.Created, direction: Direction) -> StackAnimator?, -) : AbstractStackAnimation(disableInputDuringAnimation = disableInputDuringAnimation) { - - @Composable - override fun Child( - item: AnimationItem, - onFinished: () -> Unit, - content: @Composable (child: Child.Created) -> Unit, - ) { - val animator = - remember(item.child.key, item.otherChild?.key, item.direction) { - if (item.otherChild == null) { - EmptyStackAnimator - } else { - selector(item.child, item.otherChild, item.direction) ?: EmptyStackAnimator - } - } - - val movableContent = remember { movableContentOf(content) } - - animator( - direction = item.direction, - isInitial = item.isInitial, - onFinished = onFinished, - ) { modifier -> - Box(modifier = modifier) { - movableContent(item.child) - } - } - } -} diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Scale.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Scale.kt deleted file mode 100644 index 53581bed7..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Scale.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.animation.core.FiniteAnimationSpec -import androidx.compose.animation.core.tween -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.scale - -/** - * A simple scaling animation. Front (above) children are scaling from [frontFactor] to 1.0. - * Back (below) children are scaling from 1.0 to [backFactor]. - */ -fun scale( - animationSpec: FiniteAnimationSpec = tween(), - frontFactor: Float = 1.15F, - backFactor: Float = 0.95F, -): StackAnimator = - stackAnimator(animationSpec = animationSpec) { factor, _, content -> - content( - Modifier.scale( - if (factor >= 0F) { - factor * (frontFactor - 1F) + 1F - } else { - factor * (1F - backFactor) + 1F - } - ) - ) - } diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/SimpleStackAnimation.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/SimpleStackAnimation.kt deleted file mode 100644 index 3c6b23ccf..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/SimpleStackAnimation.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.foundation.layout.Box -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import com.arkivanov.decompose.Child - -internal class SimpleStackAnimation( - disableInputDuringAnimation: Boolean, - private val selector: (Child.Created) -> StackAnimator?, -) : AbstractStackAnimation(disableInputDuringAnimation = disableInputDuringAnimation) { - - @Composable - override fun Child( - item: AnimationItem, - onFinished: () -> Unit, - content: @Composable (child: Child.Created) -> Unit, - ) { - val animator = remember(item.child.key) { selector(item.child) ?: EmptyStackAnimator } - - animator( - direction = item.direction, - isInitial = item.isInitial, - onFinished = onFinished, - ) { modifier -> - Box(modifier = modifier) { - content(item.child) - } - } - } -} diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Slide.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Slide.kt deleted file mode 100644 index 790f75627..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/Slide.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.animation.core.FiniteAnimationSpec -import androidx.compose.animation.core.tween -import androidx.compose.foundation.gestures.Orientation -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.layout - -/** - * A simple sliding animation. Children enter from one side and exit to another side. - */ -fun slide( - animationSpec: FiniteAnimationSpec = tween(), - orientation: Orientation = Orientation.Horizontal, -): StackAnimator = - stackAnimator(animationSpec = animationSpec) { factor, _, content -> - content( - when (orientation) { - Orientation.Horizontal -> Modifier.offsetXFactor(factor) - Orientation.Vertical -> Modifier.offsetYFactor(factor) - } - ) - } - -private fun Modifier.offsetXFactor(factor: Float): Modifier = - layout { measurable, constraints -> - val placeable = measurable.measure(constraints) - - layout(placeable.width, placeable.height) { - placeable.placeRelative(x = (placeable.width.toFloat() * factor).toInt(), y = 0) - } - } - -private fun Modifier.offsetYFactor(factor: Float): Modifier = - layout { measurable, constraints -> - val placeable = measurable.measure(constraints) - - layout(placeable.width, placeable.height) { - placeable.placeRelative(x = 0, y = (placeable.height.toFloat() * factor).toInt()) - } - } diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation.kt deleted file mode 100644 index f860a30ef..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimation.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.arkivanov.decompose.Child -import com.arkivanov.decompose.FaultyDecomposeApi -import com.arkivanov.decompose.router.stack.ChildStack - -/** - * Tracks the [ChildStack] changes and animates between child widget. - */ -fun interface StackAnimation { - - @Composable - operator fun invoke( - stack: ChildStack, - modifier: Modifier, - content: @Composable (child: Child.Created) -> Unit, - ) -} - -/** - * Creates an implementation of [StackAnimation] that allows different [StackAnimator]s. - * - * FaultyDecomposeApi. Please note that this API uses `movableContentOf` Compose API. - * Even though `movableContentOf` is not marked as experimental, it was known to contain bugs, - * e.g. https://issuetracker.google.com/issues/270656235, https://issuetracker.google.com/issues/290343159. - * - * @param disableInputDuringAnimation disables input and touch events while animating, default value is `true`. - * @param selector provides a [StackAnimator] for the current [Child], other [Child] and [Direction]. - */ -@FaultyDecomposeApi -fun stackAnimation( - disableInputDuringAnimation: Boolean = true, - selector: (child: Child.Created, otherChild: Child.Created, direction: Direction) -> StackAnimator?, -): StackAnimation = - MovableStackAnimation( - disableInputDuringAnimation = disableInputDuringAnimation, - selector = selector, - ) - -/** - * Creates an implementation of [StackAnimation] that allows different [StackAnimator]s. - * - * @param disableInputDuringAnimation disables input and touch events while animating, default value is `true`. - * @param selector provides a [StackAnimator] for the current [Child]. - */ -fun stackAnimation( - disableInputDuringAnimation: Boolean = true, - selector: (child: Child.Created) -> StackAnimator?, -): StackAnimation = - SimpleStackAnimation( - disableInputDuringAnimation = disableInputDuringAnimation, - selector = selector, - ) - -/** - * Creates an implementation of [StackAnimation] with the provided [StackAnimator]. - * - * @param animator a [StackAnimator] to be used for animation, default is [fade]. - * @param disableInputDuringAnimation disables input and touch events while animating, default value is `true`. - */ -fun stackAnimation( - animator: StackAnimator = fade(), - disableInputDuringAnimation: Boolean = true, -): StackAnimation = - SimpleStackAnimation( - disableInputDuringAnimation = disableInputDuringAnimation, - selector = { animator }, - ) diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationProvider.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationProvider.kt deleted file mode 100644 index c4fe768a7..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationProvider.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.runtime.compositionLocalOf - -interface StackAnimationProvider { - fun provide(): StackAnimation? -} - -val LocalStackAnimationProvider = compositionLocalOf { - object : StackAnimationProvider { - override fun provide(): StackAnimation? = null - } -} - diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator.kt deleted file mode 100644 index 976b39749..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimator.kt +++ /dev/null @@ -1,100 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.animation.core.FiniteAnimationSpec -import androidx.compose.animation.core.tween -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier - -/** - * Animates a child widget in the given [Direction]. - */ -fun interface StackAnimator { - - /** - * Animates child [content] in the given [Direction], and calls [onFinished] at the end. - * - * @param direction the [Direction] in which the animation should run. - * @param isInitial `true` if the child is the initial one (and so the animation may be skipped), `false` otherwise. - * @param onFinished must be called at the end of the animation. - * @content the composable content of the child being animated. - */ - @Composable - operator fun invoke( - direction: Direction, - isInitial: Boolean, - onFinished: () -> Unit, - content: @Composable (Modifier) -> Unit, - ) -} - -/** - * Creates an implementation of [StackAnimator] with a convenient frame-by-frame rendering. - * - * @param animationSpec a [FiniteAnimationSpec] to configure the animation. - * @param frame renders the `content` using the provided `factor` and [Direction]. Called for every animation frame. - * The `factor` argument changes as follows: - * - From 1F to 0F for [Direction.ENTER_FRONT] - * - From 0F to 1F for [Direction.EXIT_FRONT] - * - From -1F to 0F for [Direction.ENTER_BACK] - * - From 0F to -1F for [Direction.EXIT_BACK] - */ -fun stackAnimator( - animationSpec: FiniteAnimationSpec = tween(), - frame: @Composable (factor: Float, direction: Direction, content: @Composable (Modifier) -> Unit) -> Unit, -): StackAnimator = - DefaultStackAnimator( - animationSpec = animationSpec, - frame = frame - ) - -/** - * Combines (merges) the receiver [StackAnimator] with the [other] [StackAnimator]. - */ -operator fun StackAnimator.plus(other: StackAnimator): StackAnimator = - PlusStackAnimator(first = this, second = other) - -/* - * Can't be anonymous. See: - * https://github.com/JetBrains/compose-jb/issues/2688 - * https://github.com/JetBrains/compose-jb/issues/2612 - */ -private class PlusStackAnimator( - private val first: StackAnimator, - private val second: StackAnimator, -) : StackAnimator { - - @Composable - override fun invoke( - direction: Direction, - isInitial: Boolean, - onFinished: () -> Unit, - content: @Composable (Modifier) -> Unit, - ) { - val finished = remember(direction) { BooleanArray(2) } - - first( - direction = direction, - isInitial = isInitial, - onFinished = { - finished[0] = true - if (finished.all { it }) { - onFinished() - } - }, - ) { thisModifier -> - second( - direction = direction, - isInitial = isInitial, - onFinished = { - finished[1] = true - if (finished.all { it }) { - onFinished() - } - }, - ) { otherModifier -> - content(thisModifier.then(otherModifier)) - } - } - } -} diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/BackGestureHandler.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/BackGestureHandler.kt deleted file mode 100644 index f58cbcf8e..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/BackGestureHandler.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import com.arkivanov.essenty.backhandler.BackCallback -import com.arkivanov.essenty.backhandler.BackEvent -import com.arkivanov.essenty.backhandler.BackHandler - -@Composable -internal fun BackGestureHandler( - backHandler: BackHandler, - onBackStarted: (BackEvent) -> Unit = {}, - onBackProgressed: (BackEvent) -> Unit = {}, - onBackCancelled: () -> Unit = {}, - onBack: () -> Unit, -) { - DisposableEffect(backHandler) { - val callback = - BackCallback( - onBackStarted = onBackStarted, - onBackProgressed = onBackProgressed, - onBackCancelled = onBackCancelled, - onBack = onBack, - ) - - backHandler.register(callback) - onDispose { backHandler.unregister(callback) } - } -} diff --git a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimation.kt b/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimation.kt deleted file mode 100644 index c20ed27f5..000000000 --- a/extensions-compose/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/predictiveback/PredictiveBackAnimation.kt +++ /dev/null @@ -1,200 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.key -import androidx.compose.runtime.movableContentOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import com.arkivanov.decompose.Child -import com.arkivanov.decompose.Ref -import com.arkivanov.decompose.extensions.compose.stack.animation.LocalStackAnimationProvider -import com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimation -import com.arkivanov.decompose.extensions.compose.stack.animation.emptyStackAnimation -import com.arkivanov.decompose.extensions.compose.utils.InputConsumingOverlay -import com.arkivanov.decompose.router.stack.ChildStack -import com.arkivanov.essenty.backhandler.BackCallback -import com.arkivanov.essenty.backhandler.BackEvent -import com.arkivanov.essenty.backhandler.BackHandler -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch - -/** - * Wraps the provided [fallbackAnimation], handles the predictive back gesture and animates - * the transition from the current [Child] to the previous one. - * Calls [onBack] when the animation is finished. - * - * @param backHandler a source of the predictive back gesture events, see [BackHandler]. - * @param fallbackAnimation a [StackAnimation] for regular transitions. - * @param selector a selector function that is called when the predictive back gesture begins, - * returns [PredictiveBackAnimatable] responsible for animations. - * @param onBack a callback that is called when the gesture is finished. - */ -fun predictiveBackAnimation( - backHandler: BackHandler, - fallbackAnimation: StackAnimation? = null, - selector: ( - initialBackEvent: BackEvent, - exitChild: Child.Created, - enterChild: Child.Created, - ) -> PredictiveBackAnimatable = { initialBackEvent, _, _ -> - materialPredictiveBackAnimatable(initialBackEvent = initialBackEvent) - }, - onBack: () -> Unit, -): StackAnimation = - PredictiveBackAnimation( - backHandler = backHandler, - animation = fallbackAnimation, - selector = selector, - onBack = onBack, - ) - -private class PredictiveBackAnimation( - private val backHandler: BackHandler, - private val animation: StackAnimation?, - private val selector: (BackEvent, exitChild: Child.Created, enterChild: Child.Created) -> PredictiveBackAnimatable, - private val onBack: () -> Unit, -) : StackAnimation { - - @Composable - override fun invoke(stack: ChildStack, modifier: Modifier, content: @Composable (child: Child.Created) -> Unit) { - val activeKeys = remember { HashSet() } - val handler = rememberHandler(stack = stack, isGestureEnabled = { activeKeys.size == 1 }) - val animationProvider = LocalStackAnimationProvider.current - val anim = animation ?: remember(animationProvider, animationProvider::provide) ?: emptyStackAnimation() - - val childContent = - remember(content) { - movableContentOf> { child -> - key(child.key) { - content(child) - - DisposableEffect(Unit) { - activeKeys += child.key - onDispose { activeKeys -= child.key } - } - } - } - } - - Box(modifier = modifier) { - handler.items.forEach { item -> - key(item.key) { - anim( - stack = item.stack, - modifier = Modifier.fillMaxSize().then(item.modifier()), - content = childContent, - ) - } - } - - if (handler.items.size > 1) { - InputConsumingOverlay(modifier = Modifier.matchParentSize()) - } - } - - if (stack.backStack.isNotEmpty()) { - DisposableEffect(handler) { - backHandler.register(handler) - onDispose { backHandler.unregister(handler) } - } - } - } - - - @Composable - private fun rememberHandler(stack: ChildStack, isGestureEnabled: () -> Boolean): Handler { - val scope = key(stack) { rememberCoroutineScope() } - - return rememberWithLatest(stack) { previousHandler -> - Handler( - stack = stack, - scope = scope, - isGestureEnabled = isGestureEnabled, - key = previousHandler?.items?.maxOf { it.key } ?: 0, - selector = selector, - onBack = onBack, - ) - } - } - - @Composable - private fun rememberWithLatest(key: Any, supplier: (T?) -> T): T { - val ref = remember { Ref(null) } - val v = remember(key) { supplier(ref.value) } - ref.value = v - - return v - } - - private data class Item( - val stack: ChildStack, - val key: Int, - val modifier: () -> Modifier = { Modifier }, - ) - - private class Handler( - private val stack: ChildStack, - private val scope: CoroutineScope, - private val isGestureEnabled: () -> Boolean, - private val key: Int, - private val selector: (BackEvent, exitChild: Child.Created, enterChild: Child.Created) -> PredictiveBackAnimatable, - private val onBack: () -> Unit, - ) : BackCallback() { - var items: List> by mutableStateOf(listOf(Item(stack = stack, key = key))) - private set - - private var animatable: PredictiveBackAnimatable? = null - private var initialBackEvent: BackEvent? = null - - override fun onBackStarted(backEvent: BackEvent) { - initialBackEvent = backEvent - } - - override fun onBackProgressed(backEvent: BackEvent) { - val initialBackEvent = initialBackEvent - if ((initialBackEvent != null) && isGestureEnabled()) { - val animatable = selector(initialBackEvent, stack.active, stack.backStack.last()) - this.animatable = animatable - this.initialBackEvent = null - - items = - listOf( - Item(stack = stack.dropLast(), key = key + 1, modifier = animatable::enterModifier), - Item(stack = stack, key = key, modifier = animatable::exitModifier), - ) - } - - scope.launch { animatable?.animate(backEvent) } - } - - private fun ChildStack.dropLast(): ChildStack = - ChildStack(active = backStack.last(), backStack = backStack.dropLast(1)) - - override fun onBack() { - if (animatable == null) { - onBack.invoke() - } else { - scope.launch { - animatable?.finish() - animatable = null - onBack.invoke() - } - } - } - - override fun onBackCancelled() { - scope.launch { - animatable?.cancel() - animatable = null - items = listOf(Item(stack = stack, key = key)) - } - } - } -} diff --git a/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/ChildrenTest.kt b/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/ChildrenTest.kt deleted file mode 100644 index dcb7b57c8..000000000 --- a/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/ChildrenTest.kt +++ /dev/null @@ -1,263 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.text.BasicText -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.State -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onNodeWithText -import androidx.compose.ui.test.performClick -import com.arkivanov.decompose.Child -import com.arkivanov.decompose.FaultyDecomposeApi -import com.arkivanov.decompose.extensions.compose.stack.animation.StackAnimation -import com.arkivanov.decompose.extensions.compose.stack.animation.fade -import com.arkivanov.decompose.extensions.compose.stack.animation.plus -import com.arkivanov.decompose.extensions.compose.stack.animation.scale -import com.arkivanov.decompose.extensions.compose.stack.animation.slide -import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation -import com.arkivanov.decompose.router.stack.ChildStack -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.Parameterized -import kotlin.test.assertSame - -@Suppress("TestFunctionName") -@RunWith(Parameterized::class) -class ChildrenTest( - private val animation: StackAnimation?, -) { - - @get:Rule - val composeRule = createComposeRule() - - @Test - fun WHEN_active_child_and_no_back_stack_THEN_active_child_displayed() { - val state = mutableStateOf(routerState("A")) - - setContent(state) - - composeRule.onNodeWithText(text = "ChildA", substring = true).assertExists() - } - - @Test - fun GIVEN_child_A_displayed_WHEN_push_child_B_THEN_child_B_displayed() { - val state = mutableStateOf(routerState("A")) - setContent(state) - - state.setValueOnIdle(routerState("A", "B")) - - composeRule.onNodeWithText(text = "ChildB", substring = true).assertExists() - } - - @Test - fun GIVEN_child_A1_displayed_WHEN_push_child_A2_THEN_child_A2_displayed() { - val state = mutableStateOf(routerState("A1")) - setContent(state) - - state.setValueOnIdle(routerState("A1", "A2")) - - composeRule.onNodeWithText(text = "ChildA2", substring = true).assertExists() - } - - @Test - fun GIVEN_child_B_displayed_and_child_A_in_back_stack_WHEN_pop_child_B_THEN_child_A_displayed() { - val state = mutableStateOf(routerState("A")) - setContent(state) - state.setValueOnIdle(routerState("A", "B")) - - state.setValueOnIdle(routerState("A")) - - composeRule.onNodeWithText(text = "ChildA", substring = true).assertExists() - } - - @Test - fun GIVEN_child_A2_displayed_and_child_A1_in_back_stack_WHEN_pop_child_A2_THEN_child_A1_displayed() { - val state = mutableStateOf(routerState("A1")) - setContent(state) - state.setValueOnIdle(routerState("A1", "A2")) - - - state.setValueOnIdle(routerState("A1")) - - composeRule.onNodeWithText(text = "ChildA1", substring = true).assertExists() - } - - @Test - fun GIVEN_child_displayed_WHEN_new_child_instance_with_the_same_key_THEN_new_child_instance_displayed() { - val state = mutableStateOf(routerState(Child.Created(configuration = "Config", instance = Any(), key = "A"))) - var lastInstance: Any? = null - setContent(state) { lastInstance = it.instance } - - val instance2 = Any() - state.setValueOnIdle(routerState(Child.Created(configuration = "Config", instance = instance2, key = "A"))) - - assertSame(instance2, lastInstance) - } - - @Test - fun GIVEN_child_B_displayed_and_child_A_in_back_stack_WHEN_pop_child_B_THEN_state_restored_for_child_A() { - val state = mutableStateOf(routerState("A")) - setContent(state) - composeRule.onNodeWithText(text = "ChildA=0").performClick() - state.setValueOnIdle(routerState("A", "B")) - - state.setValueOnIdle(routerState("A")) - - composeRule.onNodeWithText(text = "ChildA=1").assertExists() - } - - @Test - fun GIVEN_child_A2_displayed_and_child_A1_in_back_stack_WHEN_pop_child_A2_THEN_state_restored_for_child_A1() { - val state = mutableStateOf(routerState("A1")) - setContent(state) - composeRule.onNodeWithText(text = "ChildA1=0").performClick() - state.setValueOnIdle(routerState("A1", "A2")) - - state.setValueOnIdle(routerState("A1")) - - composeRule.onNodeWithText(text = "ChildA1=1").assertExists() - } - - @Test - fun GIVEN_child_B_displayed_and_child_A_in_back_stack_WHEN_pop_child_B_and_push_child_B_THEN_state_not_restored_for_child_B() { - val state = mutableStateOf(routerState("A")) - setContent(state) - - state.setValueOnIdle(routerState("A", "B")) - composeRule.onNodeWithText(text = "ChildB=0").performClick() - - state.setValueOnIdle(routerState("A")) - state.setValueOnIdle(routerState("A", "B")) - - composeRule.onNodeWithText(text = "ChildB=0").assertExists() - } - - @Test - fun GIVEN_child_A2_displayed_and_child_A1_in_back_stack_WHEN_pop_child_A2_and_push_child_A2_THEN_state_not_restored_for_child_A2() { - val state = mutableStateOf(routerState("A1")) - setContent(state) - - state.setValueOnIdle(routerState("A1", "A2")) - composeRule.onNodeWithText(text = "ChildA2=0").performClick() - - state.setValueOnIdle(routerState("A1")) - state.setValueOnIdle(routerState("A1", "A2")) - - composeRule.onNodeWithText(text = "ChildA2=0").assertExists() - } - - @Test - fun GIVEN_child_A_displayed_WHEN_push_child_B_THEN_child_A_disposed() { - val state = mutableStateOf(routerState("A")) - setContent(state) - - state.setValueOnIdle(routerState("A", "B")) - - composeRule.onNodeWithText(text = "ChildA", substring = true).assertDoesNotExist() - } - - @Test - fun GIVEN_child_A1_displayed_WHEN_push_child_A2_THEN_child_A1_disposed() { - val state = mutableStateOf(routerState("A1")) - setContent(state) - - state.setValueOnIdle(routerState("A1", "A2")) - - composeRule.onNodeWithText(text = "ChildA1", substring = true).assertDoesNotExist() - } - - @Test - fun GIVEN_child_B_displayed_and_child_A_in_back_stack_WHEN_pop_child_B_THEN_child_B_disposed() { - val state = mutableStateOf(routerState("A")) - setContent(state) - state.setValueOnIdle(routerState("A", "B")) - - state.setValueOnIdle(routerState("A")) - - composeRule.onNodeWithText(text = "ChildB", substring = true).assertDoesNotExist() - } - - @Test - fun GIVEN_child_A2_displayed_and_child_A1_in_back_stack_WHEN_pop_child_A2_THEN_child_A2_disposed() { - val state = mutableStateOf(routerState("A1")) - setContent(state) - state.setValueOnIdle(routerState("A1", "A2")) - - state.setValueOnIdle(routerState("A1")) - - composeRule.onNodeWithText(text = "ChildA2", substring = true).assertDoesNotExist() - } - - private fun setContent( - state: State>, - content: @Composable (Child.Created) -> Unit = { - Child(name = it.key) - }, - ) { - composeRule.setContent { - Children(stack = state.value, animation = animation, content = content) - } - - composeRule.runOnIdle {} - } - - private fun routerState(vararg keys: String): ChildStack = - ChildStack( - active = child(key = keys.last()), - backStack = keys.dropLast(1).map { child(key = it) }, - ) - - private fun routerState(vararg stack: Child.Created): ChildStack = - ChildStack( - active = stack.last(), - backStack = stack.dropLast(1), - ) - - private fun child(key: String): Child.Created = - Child.Created(configuration = "Config", instance = Any(), key = key) - - @Composable - private fun Child(name: String) { - var count by rememberSaveable { mutableStateOf(0) } - - BasicText( - text = "Child$name=$count", - modifier = Modifier.clickable { count++ } - ) - } - - private fun MutableState.setValueOnIdle(value: T) { - composeRule.runOnIdle { this.value = value } - composeRule.runOnIdle {} - } - - companion object { - @Parameterized.Parameters - @JvmStatic - fun parameters(): List> = - getParameters().map { arrayOf(it) } - - @OptIn(FaultyDecomposeApi::class) - private fun getParameters(): List?> = - listOf( - null, - stackAnimation { _, _, _ -> null }, - stackAnimation { _, _, _ -> scale() }, - stackAnimation { _, _, _ -> fade() }, - stackAnimation { _, _, _ -> slide() }, - stackAnimation { _, _, _ -> scale() + fade() + slide() }, - stackAnimation { _ -> null }, - stackAnimation { _ -> scale() }, - stackAnimation { _ -> fade() }, - stackAnimation { _ -> slide() }, - stackAnimation { _ -> scale() + fade() + slide() }, - ) - } -} diff --git a/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/GetFadeAlphaTest.kt b/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/GetFadeAlphaTest.kt deleted file mode 100644 index 80c9877e5..000000000 --- a/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/GetFadeAlphaTest.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import kotlin.test.Test -import kotlin.test.assertEquals - -class GetFadeAlphaTest { - - private val cases = - listOf( - Case(factor = 1F, minAlpha = 0F, expected = 0F), - Case(factor = 0.75F, minAlpha = 0F, expected = 0.25F), - Case(factor = 0.5F, minAlpha = 0F, expected = 0.5F), - Case(factor = 0.25F, minAlpha = 0F, expected = 0.75F), - Case(factor = 0F, minAlpha = 0F, expected = 1F), - Case(factor = -0.25F, minAlpha = 0F, expected = 0.75F), - Case(factor = -0.5F, minAlpha = 0F, expected = 0.5F), - Case(factor = -0.75F, minAlpha = 0F, expected = 0.25F), - Case(factor = -1F, minAlpha = 0F, expected = 0F), - - Case(factor = 1F, minAlpha = 0.25F, expected = 0.25F), - Case(factor = 0.75F, minAlpha = 0.25F, expected = 0.4375F), - Case(factor = 0.5F, minAlpha = 0.25F, expected = 0.625F), - Case(factor = 0.25F, minAlpha = 0.25F, expected = 0.8125F), - Case(factor = 0F, minAlpha = 0.25F, expected = 1F), - Case(factor = -0.25F, minAlpha = 0.25F, expected = 0.8125F), - Case(factor = -0.5F, minAlpha = 0.25F, expected = 0.625F), - Case(factor = -0.75F, minAlpha = 0.25F, expected = 0.4375F), - Case(factor = -1F, minAlpha = 0.25F, expected = 0.25F), - - Case(factor = 1F, minAlpha = 0.5F, expected = 0.5F), - Case(factor = 0.75F, minAlpha = 0.5F, expected = 0.625F), - Case(factor = 0.5F, minAlpha = 0.5F, expected = 0.75F), - Case(factor = 0.25F, minAlpha = 0.5F, expected = 0.875F), - Case(factor = 0F, minAlpha = 0.5F, expected = 1F), - Case(factor = -0.25F, minAlpha = 0.5F, expected = 0.875F), - Case(factor = -0.5F, minAlpha = 0.5F, expected = 0.75F), - Case(factor = -0.75F, minAlpha = 0.5F, expected = 0.625F), - Case(factor = -1F, minAlpha = 0.5F, expected = 0.5F), - - Case(factor = 1F, minAlpha = 0.75F, expected = 0.75F), - Case(factor = 0.75F, minAlpha = 0.75F, expected = 0.8125F), - Case(factor = 0.5F, minAlpha = 0.75F, expected = 0.875F), - Case(factor = 0.25F, minAlpha = 0.75F, expected = 0.9375F), - Case(factor = 0F, minAlpha = 0.75F, expected = 1F), - Case(factor = -0.25F, minAlpha = 0.75F, expected = 0.9375F), - Case(factor = -0.5F, minAlpha = 0.75F, expected = 0.875F), - Case(factor = -0.75F, minAlpha = 0.75F, expected = 0.8125F), - Case(factor = -1F, minAlpha = 0.75F, expected = 0.75F), - - Case(factor = 1F, minAlpha = 1F, expected = 1F), - Case(factor = 0.75F, minAlpha = 1F, expected = 1F), - Case(factor = 0.5F, minAlpha = 1F, expected = 1F), - Case(factor = 0.25F, minAlpha = 1F, expected = 1F), - Case(factor = 0F, minAlpha = 1F, expected = 1F), - Case(factor = -0.25F, minAlpha = 1F, expected = 1F), - Case(factor = -0.5F, minAlpha = 1F, expected = 1F), - Case(factor = -0.75F, minAlpha = 1F, expected = 1F), - Case(factor = -1F, minAlpha = 1F, expected = 1F), - ) - - @Test - fun getFadeAlpha_allCases() { - cases.forEach { case -> - assertEquals( - expected = case.expected, - actual = getFadeAlpha(factor = case.factor, minAlpha = case.minAlpha), - absoluteTolerance = 0.0000001F, - message = case.toString(), - ) - } - } - - private data class Case( - val factor: Float, - val minAlpha: Float, - val expected: Float, - ) -} diff --git a/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/SimpleStackAnimationTest.kt b/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/SimpleStackAnimationTest.kt deleted file mode 100644 index b4e41519f..000000000 --- a/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/SimpleStackAnimationTest.kt +++ /dev/null @@ -1,127 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.animation.core.tween -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.compositionLocalOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.test.MainTestClock -import androidx.compose.ui.test.junit4.createComposeRule -import com.arkivanov.decompose.Child -import com.arkivanov.decompose.extensions.compose.takeSorted -import com.arkivanov.decompose.router.stack.ChildStack -import org.junit.Rule -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -@Suppress("TestFunctionName") -class SimpleStackAnimationTest { - - @get:Rule - val composeRule = createComposeRule() - - @Test - fun WHEN_animating_push_and_stack_popped_during_animation_THEN_animated_push_and_pop_fully() { - val anim = - SimpleStackAnimation( - disableInputDuringAnimation = true, - selector = { - stackAnimator(animationSpec = tween(durationMillis = 1000)) { factor, _, content -> - CompositionLocalProvider(LocalProgress provides factor) { - content(Modifier) - } - } - }, - ) - - var stack by mutableStateOf(stack("1")) - val values1 = ArrayList>() - val values2 = ArrayList>() - - composeRule.setContent { - anim(stack = stack, modifier = Modifier) { - val pair = composeRule.mainClock.currentTime to LocalProgress.current - when (it.key) { - "1" -> values1 += pair - "2" -> values2 += pair - } - } - } - - stack = stack("1", "2") - composeRule.mainClock.advanceFramesBy(millis = 500L) - stack = stack("1") - composeRule.waitForIdle() - - val v11 = values1.takeSorted(compareByDescending { it.second }) - val v21 = values2.takeSorted(compareByDescending { it.second }) - assertTrue(v11.size > 10) - assertTrue(v21.size > 10) - assertEquals(0F, v11.first().second, 0.01F) - assertEquals(-1F, v11.last().second, 0.01F) - assertEquals(1F, v21.first().second, 0.01F) - assertEquals(0F, v21.last().second, 0.01F) - - val v12 = values1.drop(v11.size - 1).takeSorted(compareBy { it.second }) - val v22 = values2.drop(v21.size - 1).takeSorted(compareBy { it.second }) - assertTrue(v12.size > 10) - assertTrue(v22.size > 10) - assertEquals(-1F, v12.first().second, 0.01F) - assertEquals(0F, v12.last().second, 0.01F) - assertEquals(0F, v22.first().second, 0.01F) - assertEquals(1F, v22.last().second, 0.01F) - } - - @Test - fun WHEN_animating_push_and_stack_popped_during_animation_THEN_first_child_restarted() { - val anim = - SimpleStackAnimation( - disableInputDuringAnimation = true, - selector = { fade(animationSpec = tween(durationMillis = 1000)) }, - ) - - var stack by mutableStateOf(stack("1")) - var counter = 0 - - composeRule.setContent { - anim(stack = stack, modifier = Modifier) { - if (it.key == "1") { - LaunchedEffect(Unit) { - counter++ - } - } - } - } - - stack = stack("1", "2") - composeRule.mainClock.advanceFramesBy(millis = 500L) - stack = stack("1") - composeRule.waitForIdle() - - assertEquals(counter, 2) - } - - private fun MainTestClock.advanceFramesBy(millis: Long) { - val endTime = currentTime + millis - while (currentTime < endTime) { - advanceTimeByFrame() - } - } - - private fun child(key: String): Child.Created = - Child.Created(configuration = "Config", instance = Any(), key = key) - - private fun stack(vararg keys: String): ChildStack = - ChildStack( - active = child(keys.last()), - backStack = keys.dropLast(1).map(::child), - ) - - private companion object { - private val LocalProgress = compositionLocalOf { 0F } - } -} diff --git a/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationDirectionsTest.kt b/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationDirectionsTest.kt deleted file mode 100644 index c3766cd1d..000000000 --- a/extensions-compose/src/jvmTest/kotlin/com/arkivanov/decompose/extensions/compose/stack/animation/StackAnimationDirectionsTest.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.arkivanov.decompose.extensions.compose.stack.animation - -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.test.junit4.createComposeRule -import com.arkivanov.decompose.Child -import com.arkivanov.decompose.extensions.compose.stack.animation.Direction.ENTER_BACK -import com.arkivanov.decompose.extensions.compose.stack.animation.Direction.ENTER_FRONT -import com.arkivanov.decompose.extensions.compose.stack.animation.Direction.EXIT_BACK -import com.arkivanov.decompose.extensions.compose.stack.animation.Direction.EXIT_FRONT -import com.arkivanov.decompose.router.stack.ChildStack -import org.junit.Rule -import org.junit.runner.RunWith -import org.junit.runners.Parameterized -import kotlin.test.Test -import kotlin.test.assertEquals - -@RunWith(Parameterized::class) -class StackAnimationDirectionsTest( - private val params: Params, -) { - - @get:Rule - val composeRule = createComposeRule() - - @Test - fun test() { - val results = HashMap() - - val animation = - SimpleStackAnimation( - disableInputDuringAnimation = false, - selector = { child -> - StackAnimator { direction, isInitial, onFinished, content -> - results[child.configuration] = direction - content(Modifier) - - DisposableEffect(direction, isInitial) { - onFinished() - onDispose {} - } - } - }, - ) - - var stack by mutableStateOf(stack(params.from)) - - composeRule.setContent { - animation(stack, Modifier) {} - } - - composeRule.runOnIdle {} - results.clear() - stack = stack(params.to) - composeRule.runOnIdle {} - - assertEquals(params.expected, results) - } - - private fun stack(configs: List): ChildStack = - ChildStack( - active = child(configs.last()), - backStack = configs.dropLast(1).map(::child), - ) - - private fun child(config: String): Child.Created = - Child.Created(configuration = config, instance = config) - - companion object { - @Parameterized.Parameters - @JvmStatic - fun parameters(): List> = - getParameters().map { arrayOf(it) } - - private fun getParameters(): List = - listOf( - Params(from = listOf("a", "b", "c"), to = listOf("a", "b"), expected = mapOf("c" to EXIT_FRONT, "b" to ENTER_BACK)), - Params(from = listOf("a", "b", "c"), to = listOf("a"), expected = mapOf("c" to EXIT_FRONT, "a" to ENTER_BACK)), - Params(from = listOf("a", "b", "c", "d"), to = listOf("a", "b"), expected = mapOf("d" to EXIT_FRONT, "b" to ENTER_BACK)), - Params(from = listOf("a", "b", "c", "d"), to = listOf("e", "b"), expected = mapOf("d" to EXIT_FRONT, "b" to ENTER_BACK)), - Params(from = listOf("a", "b", "c"), to = listOf("d", "a"), expected = mapOf("c" to EXIT_FRONT, "a" to ENTER_BACK)), - Params(from = listOf("a"), to = listOf("a", "b"), expected = mapOf("b" to ENTER_FRONT, "a" to EXIT_BACK)), - Params(from = listOf("a", "b"), to = listOf("a", "b", "c"), expected = mapOf("c" to ENTER_FRONT, "b" to EXIT_BACK)), - Params(from = listOf("a", "b"), to = listOf("a", "c"), expected = mapOf("c" to ENTER_FRONT, "b" to EXIT_BACK)), - Params(from = listOf("a", "b"), to = listOf("c", "d"), expected = mapOf("d" to ENTER_FRONT, "b" to EXIT_BACK)), - Params(from = listOf("a"), to = listOf("b"), expected = mapOf("b" to ENTER_FRONT, "a" to EXIT_BACK)), - Params(from = listOf("a"), to = listOf("b", "c"), expected = mapOf("c" to ENTER_FRONT, "a" to EXIT_BACK)), - Params(from = listOf("a", "b"), to = listOf("a", "c", "d"), expected = mapOf("d" to ENTER_FRONT, "b" to EXIT_BACK)), - Params(from = listOf("a", "b"), to = listOf("c"), expected = mapOf("c" to ENTER_FRONT, "b" to EXIT_BACK)), - Params(from = listOf("a", "b", "c"), to = listOf("a", "d"), expected = mapOf("d" to ENTER_FRONT, "c" to EXIT_BACK)), - Params(from = listOf("a", "b"), to = listOf("c", "d"), expected = mapOf("d" to ENTER_FRONT, "b" to EXIT_BACK)), - Params(from = listOf("a", "b"), to = listOf("b", "a"), expected = mapOf("a" to ENTER_FRONT, "b" to EXIT_BACK)), - Params(from = listOf("a", "b"), to = listOf("b"), expected = mapOf("b" to ENTER_FRONT)), - Params(from = listOf("a", "b"), to = listOf("c", "b"), expected = mapOf("b" to ENTER_FRONT)), - Params(from = listOf("b", "c"), to = listOf("a", "b", "c"), expected = mapOf("c" to ENTER_FRONT)), - ) - } - - class Params( - val from: List, - val to: List, - val expected: Map, - ) -}