From 6fa7b41d6f3050f47194d5431eb16a3b4c6e7c10 Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Sat, 1 Jul 2023 08:55:43 +0100 Subject: [PATCH 1/7] Added retainedComponent docs --- docs/component/instance-retaining.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/component/instance-retaining.md b/docs/component/instance-retaining.md index 36f4d3a6e..355d60e5b 100644 --- a/docs/component/instance-retaining.md +++ b/docs/component/instance-retaining.md @@ -28,3 +28,23 @@ class SomeComponent( } } ``` + +## Retained components (since v2.1.0-alpha-03) + +Although discouraged, it is still possible to have all components retained over configuration changes on Android. On the one hand, this makes `InstanceKeeper` no longer required. But on the other hand, this prevents from supplying dependencies that capture the hosting `Activity` or `Fragment`. + +!!!warning + Pay attention when supplying dependencies to a retained component to avoid leaking the hosting `Activity` or `Fragment`. + +```kotlin +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val root = + retainedComponent { componentContext -> + DefaultRootComponent(componentContext) + } + } +} +``` From bfeee6e7c013a14f7e4caa0b74f7a651edccc2fb Mon Sep 17 00:00:00 2001 From: Tiebe Groosman Date: Sun, 2 Jul 2023 19:31:35 +0200 Subject: [PATCH 2/7] Typo fix --- docs/extensions/compose.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extensions/compose.md b/docs/extensions/compose.md index c78dd5b3c..2e61b8ae8 100644 --- a/docs/extensions/compose.md +++ b/docs/extensions/compose.md @@ -403,7 +403,7 @@ val backDispatcher = BackDispatcher() val componentContext = DefaultComponentContext( lifecycle = lifecycle, - backHandler = backHandler, // Pass BackDispatcher here + backHandler = backDispatcher, // Pass BackDispatcher here ) val root = DefaultRootComponent(componentContext = componentContext) From 0f3b440807a73572f19cd4ef0ba3f3cf512a886f Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Thu, 13 Jul 2023 13:33:41 +0100 Subject: [PATCH 3/7] Avoid using stackAnimation with lambda in samples due to a bug in movableContentOf --- .../sample/shared/counters/CountersContent.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sample/shared/compose/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/CountersContent.kt b/sample/shared/compose/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/CountersContent.kt index b2abf013a..180882387 100644 --- a/sample/shared/compose/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/CountersContent.kt +++ b/sample/shared/compose/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/CountersContent.kt @@ -8,10 +8,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.arkivanov.decompose.extensions.compose.jetbrains.stack.Children import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.fade -import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.isFront import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.plus import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.scale -import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.slide import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.stackAnimation import com.arkivanov.decompose.router.stack.ChildStack import com.arkivanov.decompose.value.MutableValue @@ -25,13 +23,15 @@ internal fun CountersContent(component: CountersComponent, modifier: Modifier = Children( stack = component.childStack, modifier = modifier, - animation = stackAnimation { _, _, direction -> - if (direction.isFront) { - slide() + fade() - } else { - scale(frontFactor = 1F, backFactor = 0.7F) + fade() - } - }, + // Workaround for https://issuetracker.google.com/issues/270656235 + animation = stackAnimation(fade() + scale()) +// animation = stackAnimation { _, _, direction -> +// if (direction.isFront) { +// slide() + fade() +// } else { +// scale(frontFactor = 1F, backFactor = 0.7F) + fade() +// } +// }, ) { CounterContent( component = it.instance, From e09a57d718834fd953aabb28c052353647cb5113 Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Sat, 22 Jul 2023 12:14:45 +0100 Subject: [PATCH 4/7] Update samples.md --- docs/samples.md | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/docs/samples.md b/docs/samples.md index 8bfe569d9..dba3a2230 100644 --- a/docs/samples.md +++ b/docs/samples.md @@ -64,30 +64,6 @@ Content: -## Sample Todo List App - - - -The Sample Todo List App demonstrates the following features: - -* Multiplatform: Android, iOS, Desktop and Web -* Shared JetBrains Compose UI for Android and Desktop apps -* JetBrains (multiplatform) Compose UI for the Web browser app -* SwiftUI for iOS app -* Nested components -* Shared routing with view state preservation -* Using `Lifecycle` -* Multi-module structure (one component per module) -* Inter-component communication (via [Reaktive](https://github.com/badoo/Reaktive), just an example) -* MVI using [MVIKotlin](https://github.com/arkivanov/MVIKotlin) -* Data persistence using [SQLDelight](https://github.com/cashapp/sqldelight) - -Please refer to the [sample's readme](https://github.com/JetBrains/compose-jb/blob/master/examples/todoapp/README.md) for more information. - -### Source Code - -The Sample Todo List App can be found in the JetBrains Compose repository [here](https://github.com/JetBrains/compose-jb/tree/master/examples/todoapp). - ## Sample Greetings App ![](media/SampleGreetingsDemo.gif) From 1d85476e54dad750954f0a9c5731b3290960665f Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Wed, 26 Jul 2023 19:26:02 +0100 Subject: [PATCH 5/7] Updated browser-history docs --- docs/navigation/stack/browser-history.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/navigation/stack/browser-history.md b/docs/navigation/stack/browser-history.md index 6c67c7abc..470cd3356 100644 --- a/docs/navigation/stack/browser-history.md +++ b/docs/navigation/stack/browser-history.md @@ -51,11 +51,11 @@ config.devServer = { Using `WebHistoryController` is easy: -1. Create an instance of `DefaultWebHistoryController` in the JS app and pass it via constructor to a component responsible for -navigation (typically it is the root component) -2. In the component, call the `WebHistoryController.attach` method and supply all arguments -3. In the JS app, pass an initial deeplink to the component -4. Use the deeplink in the component to generate an initial back stack +1. Create an instance of `DefaultWebHistoryController` in the JS app and pass it via constructor to a component responsible for navigation (typically it is the root component). +2. Create `Child Stack` and use `WebHistoryController#historyPaths` property for initial stack. This is required for cases when the page is reloaded (refreshed), so that the stack is aligned with te browser history. +3. In the component, call the `WebHistoryController.attach` method and supply all arguments. +4. In the JS app, pass an initial deeplink to the component. +5. Use the deeplink in the component to generate an initial back stack. ### Example From ba84a2b15de80a983f29ed32db0b13ed8cfe0d2b Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Wed, 26 Jul 2023 20:09:44 +0100 Subject: [PATCH 6/7] Annotated stackAnimation function that uses movableContentOf as FaultyDecomposeApi --- decompose/api/android/decompose.api | 3 +++ decompose/api/jvm/decompose.api | 3 +++ .../kotlin/com/arkivanov/decompose/Annotations.kt | 8 ++++++++ .../compose/jetbrains/stack/animation/StackAnimation.kt | 6 ++++++ .../compose/jetpack/stack/animation/StackAnimation.kt | 6 ++++++ 5 files changed, 26 insertions(+) diff --git a/decompose/api/android/decompose.api b/decompose/api/android/decompose.api index 37612bb57..24fc1a377 100644 --- a/decompose/api/android/decompose.api +++ b/decompose/api/android/decompose.api @@ -64,6 +64,9 @@ public final class com/arkivanov/decompose/DefaultComponentContextBuilderKt { public abstract interface annotation class com/arkivanov/decompose/ExperimentalDecomposeApi : java/lang/annotation/Annotation { } +public abstract interface annotation class com/arkivanov/decompose/FaultyDecomposeApi : java/lang/annotation/Annotation { +} + public abstract interface annotation class com/arkivanov/decompose/InternalDecomposeApi : java/lang/annotation/Annotation { } diff --git a/decompose/api/jvm/decompose.api b/decompose/api/jvm/decompose.api index 7e923224f..1ae0459c0 100644 --- a/decompose/api/jvm/decompose.api +++ b/decompose/api/jvm/decompose.api @@ -50,6 +50,9 @@ public final class com/arkivanov/decompose/DefaultComponentContext : com/arkivan public abstract interface annotation class com/arkivanov/decompose/ExperimentalDecomposeApi : java/lang/annotation/Annotation { } +public abstract interface annotation class com/arkivanov/decompose/FaultyDecomposeApi : java/lang/annotation/Annotation { +} + public abstract interface annotation class com/arkivanov/decompose/InternalDecomposeApi : java/lang/annotation/Annotation { } diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/Annotations.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/Annotations.kt index 21845efc3..33cf52357 100644 --- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/Annotations.kt +++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/Annotations.kt @@ -14,3 +14,11 @@ annotation class InternalDecomposeApi @RequiresOptIn(level = RequiresOptIn.Level.WARNING) @Retention(AnnotationRetention.BINARY) annotation class ExperimentalDecomposeApi + +/** + * Marks Decompose API, the implementation of which may contain bugs or known to contain bugs. + * See the docs of the annotated API for more information. + */ +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +annotation class FaultyDecomposeApi diff --git a/extensions-compose-jetbrains/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/jetbrains/stack/animation/StackAnimation.kt b/extensions-compose-jetbrains/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/jetbrains/stack/animation/StackAnimation.kt index 5dc056dbb..cb8afea66 100644 --- a/extensions-compose-jetbrains/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/jetbrains/stack/animation/StackAnimation.kt +++ b/extensions-compose-jetbrains/src/commonMain/kotlin/com/arkivanov/decompose/extensions/compose/jetbrains/stack/animation/StackAnimation.kt @@ -3,6 +3,7 @@ package com.arkivanov.decompose.extensions.compose.jetbrains.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 /** @@ -21,9 +22,14 @@ fun interface StackAnimation { /** * 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 is 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?, diff --git a/extensions-compose-jetpack/src/main/java/com/arkivanov/decompose/extensions/compose/jetpack/stack/animation/StackAnimation.kt b/extensions-compose-jetpack/src/main/java/com/arkivanov/decompose/extensions/compose/jetpack/stack/animation/StackAnimation.kt index 9fa564ab5..a38556874 100644 --- a/extensions-compose-jetpack/src/main/java/com/arkivanov/decompose/extensions/compose/jetpack/stack/animation/StackAnimation.kt +++ b/extensions-compose-jetpack/src/main/java/com/arkivanov/decompose/extensions/compose/jetpack/stack/animation/StackAnimation.kt @@ -3,6 +3,7 @@ package com.arkivanov.decompose.extensions.compose.jetpack.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 /** @@ -21,9 +22,14 @@ fun interface StackAnimation { /** * 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 is 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?, From 83023d7602823917d40f728f355befaef37145eb Mon Sep 17 00:00:00 2001 From: Arkadii Ivanov Date: Wed, 26 Jul 2023 20:48:11 +0100 Subject: [PATCH 7/7] Bumped version to 2.0.1 --- deps.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps.versions.toml b/deps.versions.toml index 6de28c2c2..1d5a29e9b 100644 --- a/deps.versions.toml +++ b/deps.versions.toml @@ -1,6 +1,6 @@ [versions] -decompose = "2.0.0" +decompose = "2.0.1" kotlin = "1.8.20" essenty = "1.1.0" parcelizeDarwin = "0.1.4"