Skip to content

Commit

Permalink
Merge pull request #747 from arkivanov/push-delicate
Browse files Browse the repository at this point in the history
Annotate StackNavigator#push as delicate API
  • Loading branch information
arkivanov authored Jul 29, 2024
2 parents 4cb68bc + 06f4a03 commit d16e901
Show file tree
Hide file tree
Showing 9 changed files with 30 additions and 8 deletions.
3 changes: 3 additions & 0 deletions decompose/api/android/decompose.api
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ public final class com/arkivanov/decompose/DefaultComponentContextBuilderKt {
public static synthetic fun defaultComponentContext$default (Landroidx/savedstate/SavedStateRegistryOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/decompose/DefaultComponentContext;
}

public abstract interface annotation class com/arkivanov/decompose/DelicateDecomposeApi : java/lang/annotation/Annotation {
}

public abstract interface annotation class com/arkivanov/decompose/ExperimentalDecomposeApi : java/lang/annotation/Annotation {
}

Expand Down
3 changes: 3 additions & 0 deletions decompose/api/decompose.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ final val com.arkivanov.decompose.router.stack/items // com.arkivanov.decompose.
final var com.arkivanov.decompose.errorhandler/onDecomposeError // com.arkivanov.decompose.errorhandler/onDecomposeError|{}onDecomposeError[0]
final fun <get-onDecomposeError>(): kotlin/Function1<kotlin/Exception, kotlin/Unit> // com.arkivanov.decompose.errorhandler/onDecomposeError.<get-onDecomposeError>|<get-onDecomposeError>(){}[0]
final fun <set-onDecomposeError>(kotlin/Function1<kotlin/Exception, kotlin/Unit>) // com.arkivanov.decompose.errorhandler/onDecomposeError.<set-onDecomposeError>|<set-onDecomposeError>(kotlin.Function1<kotlin.Exception,kotlin.Unit>){}[0]
open annotation class com.arkivanov.decompose/DelicateDecomposeApi : kotlin/Annotation { // com.arkivanov.decompose/DelicateDecomposeApi|null[0]
constructor <init>() // com.arkivanov.decompose/DelicateDecomposeApi.<init>|<init>(){}[0]
}
open annotation class com.arkivanov.decompose/ExperimentalDecomposeApi : kotlin/Annotation { // com.arkivanov.decompose/ExperimentalDecomposeApi|null[0]
constructor <init>() // com.arkivanov.decompose/ExperimentalDecomposeApi.<init>|<init>(){}[0]
}
Expand Down
3 changes: 3 additions & 0 deletions decompose/api/jvm/decompose.api
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ public final class com/arkivanov/decompose/DefaultComponentContext : com/arkivan
public fun getStateKeeper ()Lcom/arkivanov/essenty/statekeeper/StateKeeper;
}

public abstract interface annotation class com/arkivanov/decompose/DelicateDecomposeApi : java/lang/annotation/Annotation {
}

public abstract interface annotation class com/arkivanov/decompose/ExperimentalDecomposeApi : java/lang/annotation/Annotation {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ annotation class ExperimentalDecomposeApi
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY)
annotation class FaultyDecomposeApi

/**
* Marks delicate Decompose API that requires special attention when used.
* See the docs of the annotated API for more information.
*/
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY)
annotation class DelicateDecomposeApi
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.arkivanov.decompose.router.stack

import com.arkivanov.decompose.DelicateDecomposeApi

/**
* A convenience method for [StackNavigator.navigate].
*/
Expand All @@ -11,12 +13,15 @@ fun <C : Any> StackNavigator<C>.navigate(transformer: (stack: List<C>) -> List<C
* Pushes the provided [configuration] at the top of the stack.
*
* Decompose will throw an exception if the provided [configuration] is already present in the stack.
* This usually happens when a component is pushed on user interaction (e.g. a button click).
* Consider using [pushNew] instead.
* You can also try enabling the experimental
* [Duplicate Configurations][com.arkivanov.decompose.DecomposeExperimentFlags.duplicateConfigurationsEnabled] feature
* to avoid the error.
* to avoid the error. But still, pushing duplicated components on top of the stack might be wrong.
*
* @param onComplete called when the navigation is finished (either synchronously or asynchronously).
*/
@DelicateDecomposeApi
inline fun <C : Any> StackNavigator<C>.push(configuration: C, crossinline onComplete: () -> Unit = {}) {
navigate(transformer = { it + configuration }, onComplete = { _, _ -> onComplete() })
}
Expand Down
2 changes: 1 addition & 1 deletion docs/navigation/stack/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ There are `StackNavigator` [extension functions](https://github.com/arkivanov/De

### push(configuration)

Pushes the provided `Configuration` at the top of the stack. Decompose will throw an exception if the provided `Configuration` is already present in the stack.
Pushes the provided `Configuration` at the top of the stack. Decompose will throw an exception if the provided `Configuration` is already present in the stack. This usually happens when a component is pushed on user interaction (e.g. a button click). Consider using [pushNew](#pushnewconfiguration) instead.

!!! note "Illustration"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.items
import com.arkivanov.decompose.router.stack.navigate
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.router.stack.push
import com.arkivanov.decompose.router.stack.pushNew
import com.arkivanov.decompose.value.Value
import com.arkivanov.sample.shared.cards.card.CardComponent
import com.arkivanov.sample.shared.cards.card.DefaultCardComponent
Expand Down Expand Up @@ -54,7 +54,7 @@ class DefaultCardsComponent(

val maxNumber = _stack.items.maxOf { it.configuration.number }

navigation.push(
navigation.pushNew(
Config(
color = COLORS[maxNumber % COLORS.size],
number = maxNumber + 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.router.stack.popTo
import com.arkivanov.decompose.router.stack.push
import com.arkivanov.decompose.router.stack.pushNew
import com.arkivanov.decompose.value.Value
import com.arkivanov.sample.shared.counters.counter.CounterComponent
import com.arkivanov.sample.shared.counters.counter.DefaultCounterComponent
Expand Down Expand Up @@ -36,7 +36,7 @@ internal class DefaultCountersComponent(
componentContext = componentContext,
title = "Counter ${config.index}",
isBackEnabled = config.isBackEnabled,
onNext = { navigation.push(Config(index = config.index + 1, isBackEnabled = true)) },
onNext = { navigation.pushNew(Config(index = config.index + 1, isBackEnabled = true)) },
onPrev = navigation::pop,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.router.stack.push
import com.arkivanov.decompose.router.stack.pushNew
import com.arkivanov.decompose.value.Value
import com.arkivanov.sample.shared.dynamicfeatures.DynamicFeaturesComponent.Child
import com.arkivanov.sample.shared.dynamicfeatures.DynamicFeaturesComponent.Child.Feature1Child
Expand Down Expand Up @@ -51,7 +51,7 @@ internal class DefaultDynamicFeaturesComponent(
factory = { featureComponentContext ->
Feature1(
componentContext = featureComponentContext,
onFeature2 = { navigation.push(Config.Feature2(magicNumber = Random.nextInt())) },
onFeature2 = { navigation.pushNew(Config.Feature2(magicNumber = Random.nextInt())) },
)
}
)
Expand Down

0 comments on commit d16e901

Please sign in to comment.