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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ That's the whole flow. See [enro.dev](https://enro.dev) for the full guide.
## Learn Enro

- **Documentation:** [enro.dev](https://enro.dev) — installation, concepts, results, animations, testing, platform guides, and the migration guide from Enro 2.
- **Recipes:** [`recipes/`](./recipes/src/commonMain/kotlin/dev/enro/recipes) — every concept (dialogs, bottom sheets, list-detail, tabs, deep links, managed flows, shared view models, custom animations) is a small runnable sample.
- **Recipes:** [`recipes/`](./recipes/common/src/commonMain/kotlin/dev/enro/recipes) — every concept (dialogs, bottom sheets, list-detail, tabs, deep links, managed flows, shared view models, custom animations) is a small runnable sample.
- **API reference:** generate with `./gradlew dokkaGenerate`; the multi-module site lands at `build/dokka/html/index.html`. Also published as a `-javadoc.jar` alongside each artifact on Maven Central.
- **Changelog:** [CHANGELOG.md](./CHANGELOG.md).

Expand Down
10 changes: 5 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ subprojects {
tasks.register("continuousIntegration") {
val continuousIntegration = this
tasks.findByName("lintDebug")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("testDebugUnitTest")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("testAndroidHostTest")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("desktopTest")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("wasmJsBrowserTest")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("testDebugWithEmulatorWtf")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("testWithEmulatorWtf")?.let { continuousIntegration.dependsOn(it) }
// Compile-only fallbacks so modules without tests (e.g. recipes)
// are still build-checked by CI. For modules with tests, these are
// no-ops — the test tasks above already depend on compilation.
tasks.findByName("compileKotlinDesktop")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("compileDebugKotlinAndroid")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("compileAndroidMain")?.let { continuousIntegration.dependsOn(it) }
tasks.findByName("compileKotlinWasmJs")?.let { continuousIntegration.dependsOn(it) }
}

Expand Down Expand Up @@ -127,11 +127,11 @@ tasks.register<Exec>("publishEnroLocal") {
commandLine(
"./gradlew",
":enro-processor:publishMavenPublicationToMavenLocal",
":enro-annotations:publishAndroidReleasePublicationToMavenLocal",
":enro-annotations:publishAndroidPublicationToMavenLocal",
":enro-annotations:publishDesktopPublicationToMavenLocal",

"publishKotlinMultiplatformPublicationToMavenLocal",
"publishAndroidReleasePublicationToMavenLocal",
"publishAndroidPublicationToMavenLocal",
"publishDesktopPublicationToMavenLocal",
// "publishFrontendJsPublicationToMavenLocal",
"publishIosArm64PublicationToMavenLocal",
Expand Down
26 changes: 6 additions & 20 deletions buildSrc/src/main/kotlin/ConfigureCompose.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
import com.android.build.api.dsl.AndroidResources
import com.android.build.api.dsl.BuildFeatures
import com.android.build.api.dsl.BuildType
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.dsl.DefaultConfig
import com.android.build.api.dsl.Installation
import com.android.build.api.dsl.ProductFlavor
import com.android.build.gradle.BaseExtension
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
Expand Down Expand Up @@ -64,6 +57,9 @@ internal fun Project.configureComposeMultiplatform() {
androidMain.dependencies {
implementation(compose.preview)
implementation(libs.compose.activity)
// The KMP library plugin has no build variants, so ui-tooling is added to
// androidMain rather than a debug-only configuration.
implementation(compose.uiTooling)
}
commonMain.dependencies {
implementation(compose.runtime)
Expand All @@ -82,17 +78,7 @@ internal fun Project.configureComposeMultiplatform() {
}
}
}

@Suppress("UNCHECKED_CAST")
val androidExtension =
project.extensions.getByType(CommonExtension::class) as CommonExtension<BuildFeatures, BuildType, DefaultConfig, ProductFlavor, AndroidResources, Installation>

androidExtension.apply {
buildFeatures {
compose = true
}
project.dependencies {
"debugImplementation"(compose.uiTooling)
}
}
// No `buildFeatures { compose = true }` needed here — the Compose compiler is applied
// across all KMP targets (incl. Android) by the `org.jetbrains.kotlin.plugin.compose`
// plugin above.
}
21 changes: 6 additions & 15 deletions buildSrc/src/main/kotlin/ConfigureMultiplatformLibrary.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import com.android.build.api.dsl.LibraryExtension
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.the

class ConfigureMultiplatformLibrary : Plugin<Project> {
override fun apply(project: Project) {
Expand All @@ -19,17 +16,11 @@ class ConfigureMultiplatformLibraryWithJs : Plugin<Project> {
internal fun Project.configureMultiplatformLibrary(
js: Boolean,
) {
val libs = project.the<LibrariesForLibs>()
project.plugins.apply("com.android.library")
// KMP libraries with an Android target use the dedicated Android-KMP library plugin.
// The KMP plugin is applied first so the `androidLibrary {}` DSL it contributes is
// available; minSdk/compileSdk/namespace are configured there (see
// configureKotlinMultiplatform).
project.plugins.apply("org.jetbrains.kotlin.multiplatform")
project.plugins.apply("com.android.kotlin.multiplatform.library")
project.configureKotlinMultiplatform(js = js)

val androidExtension = project.extensions.getByType(LibraryExtension::class.java)
androidExtension.apply {
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
}
testOptions {
targetSdk = libs.versions.android.targetSdk.get().toInt()
}
}
}
76 changes: 35 additions & 41 deletions buildSrc/src/main/kotlin/Project.configureKotlinMultiplatform.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

import com.android.build.api.dsl.*
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionAware
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
import org.jetbrains.kotlin.gradle.dsl.JsSourceMapEmbedMode
Expand Down Expand Up @@ -38,19 +38,6 @@ internal fun Project.configureKotlinMultiplatform(
project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kotlinMultiplatformExtension.apply {
explicitApi = ExplicitApiMode.Strict
if (android) {
androidTarget {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
freeCompilerArgs.addAll(
"-P",
"plugin:org.jetbrains.kotlin.parcelize:additionalAnnotation=dev.enro.annotations.Parcelize"
)
freeCompilerArgs.addAll("-Xexpect-actual-classes")
optIn.addAll(*optIns)
}
}
}

if (desktop) {
jvm("desktop") {
Expand Down Expand Up @@ -147,35 +134,42 @@ internal fun Project.configureKotlinMultiplatform(
}

if (android) {
@Suppress("UNCHECKED_CAST")
val androidExtension =
project.extensions.getByType(CommonExtension::class) as CommonExtension<BuildFeatures, BuildType, DefaultConfig, ProductFlavor, AndroidResources, Installation>

androidExtension.apply {
namespace = project.projectName.packageName
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// Configure the Android library target contributed by the
// `com.android.kotlin.multiplatform.library` plugin. In build scripts this is the
// `kotlin { androidLibrary { ... } }` accessor; from a binary convention plugin we
// reach the same target via the KMP extension's ExtensionAware container.
val androidNamespace = project.projectName.packageName
val compileSdkVersion = libs.versions.android.compileSdk.get().toInt()
val minSdkVersion = libs.versions.android.minSdk.get().toInt()
// "androidLibrary" (rather than the "android" alias) so this resolves on AGP 9.0,
// whose Android plugin is the latest currently supported by IntelliJ. Both names
// refer to the same target on AGP 9.1+.
val androidLibrary = (kotlinMultiplatformExtension as ExtensionAware).extensions
.getByName("androidLibrary") as KotlinMultiplatformAndroidLibraryTarget
androidLibrary.apply {
namespace = androidNamespace
compileSdk = compileSdkVersion
minSdk = minSdkVersion

// The KMP library plugin disables Android resource processing (and the
// generated R class) by default; enable it so modules with src/androidMain/res
// (and code that references R) build. No-op for modules without resources.
androidResources {
enable = true
}

sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
sourceSets["main"].res.srcDirs("src/androidMain/res")
sourceSets["main"].resources.srcDirs("src/commonMain/resources")

packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
// Android test components (`withHostTest`/`withDeviceTest`) can each be
// enabled at most once, so they're opted into per-module rather than here
// (only enro-runtime currently runs Android host tests for its commonTest).

compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
freeCompilerArgs.addAll(
"-P",
"plugin:org.jetbrains.kotlin.parcelize:additionalAnnotation=dev.enro.annotations.Parcelize"
)
freeCompilerArgs.addAll("-Xexpect-actual-classes")
optIn.addAll(*optIns)
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions docs/ghpages/docs/advanced/animations.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ sample items.
shared icon and title.
- [Navigation Destinations → Custom enter/exit on overlays](../core-concepts/navigation-destinations.md#custom-enterexit-on-overlays).

[animations-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/animations/AnimatedNavigation.kt
[staggered-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/animations/StaggeredAnimations.kt
[sharedelements-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/sharedelements/SharedElementAnimations.kt
[recipes-component]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/RecipesComponent.kt
[animations-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/animations/AnimatedNavigation.kt
[staggered-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/animations/StaggeredAnimations.kt
[sharedelements-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/sharedelements/SharedElementAnimations.kt
[recipes-component]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/RecipesComponent.kt
4 changes: 2 additions & 2 deletions docs/ghpages/docs/advanced/path-bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,5 +235,5 @@ The web platform docs cover the URL/history wiring in detail — see
[Advanced Deep Link][advanced-deep-link] — full working examples of
annotated and programmatic bindings respectively.

[basic-deep-link]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/deeplink/BasicDeepLink.kt
[advanced-deep-link]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/deeplink/AdvancedDeepLink.kt
[basic-deep-link]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/deeplink/BasicDeepLink.kt
[advanced-deep-link]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/deeplink/AdvancedDeepLink.kt
2 changes: 1 addition & 1 deletion docs/ghpages/docs/advanced/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,4 @@ contract.
- [OpenedTimestampPlugin recipe][timestamp-recipe] — the worked example
above.

[timestamp-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/plugins/OpenedTimestampPlugin.kt
[timestamp-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/plugins/OpenedTimestampPlugin.kt
2 changes: 1 addition & 1 deletion docs/ghpages/docs/advanced/results.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,4 @@ back to whoever opened `EditProfile`. See
- [Embedded result flows](results/embedded-result-flows.md) and
[managed result flows](results/managed-result-flows.md).

[results-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/results/ReturningResults.kt
[results-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/results/ReturningResults.kt
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,4 @@ straight-line-able?* If yes, use a managed flow; if no, use callbacks.
conditional sequences.
- [Returning Results recipe][results-recipe] — the canonical small example.

[results-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/results/ReturningResults.kt
[results-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/results/ReturningResults.kt
2 changes: 1 addition & 1 deletion docs/ghpages/docs/advanced/results/managed-result-flows.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,4 @@ with all previous results intact.
enough.
- [Managed flow recipe][managedflow-recipe] — full runnable example.

[managedflow-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/managedflow/ManagedFlow.kt
[managedflow-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/managedflow/ManagedFlow.kt
2 changes: 1 addition & 1 deletion docs/ghpages/docs/advanced/synthetic-destinations.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,4 +361,4 @@ the operation through `container.execute(...)` as the
- [Migrating from v2](../migrating-from-v2.md) — `sendResult` /
`forwardResult` from Enro 2 are now `complete` / `completeFrom`.

[synthetic-recipes]: https://github.com/isaac-udy/Enro/tree/main/recipes/src/commonMain/kotlin/dev/enro/recipes/synthetic
[synthetic-recipes]: https://github.com/isaac-udy/Enro/tree/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/synthetic
4 changes: 2 additions & 2 deletions docs/ghpages/docs/advanced/view-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,5 @@ For a small inline example, see the [shared ViewModel recipe][shared-recipe].
- [Basic ViewModel recipe][basic-recipe] and
[Shared ViewModel recipe][shared-recipe].

[basic-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/viewmodel/BasicViewModel.kt
[shared-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/viewmodel/SharedViewModel.kt
[basic-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/viewmodel/BasicViewModel.kt
[shared-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/viewmodel/SharedViewModel.kt
6 changes: 3 additions & 3 deletions docs/ghpages/docs/core-concepts/navigation-containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,6 @@ Two recipes go deeper on this pattern:
- [Animations](../advanced/animations.md) — `NavigationAnimations` and per-element animation.
- Recipes: [list-detail][listdetail-recipe], [tabs][tabs-recipe], [multiple back stacks][multistack-recipe].

[listdetail-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/listdetail/ListDetailNavigation.kt
[tabs-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/tabs/TabNavigation.kt
[multistack-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/multiplestacks/MultipleBackStacks.kt
[listdetail-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/listdetail/ListDetailNavigation.kt
[tabs-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/tabs/TabNavigation.kt
[multistack-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/multiplestacks/MultipleBackStacks.kt
6 changes: 3 additions & 3 deletions docs/ghpages/docs/core-concepts/navigation-destinations.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,6 @@ runtime takes care of bridging it. See the
- [Animations](../advanced/animations.md) — animating destinations and their content.
- [Recipes][recipes] — every metadata style and several custom scene strategies.

[entryprovider-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/entryprovider/DestinationRegistration.kt
[listdetail-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/listdetail/ListDetailNavigation.kt
[recipes]: https://github.com/isaac-udy/Enro/tree/main/recipes/src/commonMain/kotlin/dev/enro/recipes
[entryprovider-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/entryprovider/DestinationRegistration.kt
[listdetail-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/listdetail/ListDetailNavigation.kt
[recipes]: https://github.com/isaac-udy/Enro/tree/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes
2 changes: 1 addition & 1 deletion docs/ghpages/docs/core-concepts/navigation-handles.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,4 @@ When the user navigates back, the same handle resumes.
- [View Models](../advanced/view-models.md) — `by navigationHandle<T>()` inside a ViewModel.
- [Request-close confirmation recipe][requestclose-recipe] — full unsaved-changes example.

[requestclose-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/requestclose/RequestCloseConfirmation.kt
[requestclose-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/requestclose/RequestCloseConfirmation.kt
6 changes: 3 additions & 3 deletions docs/ghpages/docs/core-concepts/navigation-keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,6 @@ See the [modular navigation recipe][modular-recipe] for a worked example.
- [Results](../advanced/results.md) — how `WithResult` keys produce and consume values.
- [Basic recipe][basic-recipe] — minimal end-to-end example.

[basic-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/basic/BasicNavigation.kt
[modular-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/modular/ModularNavigation.kt
[timestamp-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/src/commonMain/kotlin/dev/enro/recipes/plugins/OpenedTimestampPlugin.kt
[basic-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/basic/BasicNavigation.kt
[modular-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/modular/ModularNavigation.kt
[timestamp-recipe]: https://github.com/isaac-udy/Enro/blob/main/recipes/common/src/commonMain/kotlin/dev/enro/recipes/plugins/OpenedTimestampPlugin.kt
Loading
Loading