From 6c2251479298060744ed43be179885d806c83f63 Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Wed, 11 Dec 2024 14:22:42 +0100 Subject: [PATCH] refactor(kmp): migrate adaptive layout to Compose Multiplatform. --- androidApp/build.gradle.kts | 4 +-- .../conventions/PresentationLibraryPlugin.kt | 8 ++--- features/main/main/build.gradle.kts | 3 +- .../partners/presentation/PartnersAdaptive.kt | 15 ++++++---- .../presentation/ScheduleGridAdaptive.kt | 0 .../schedules-sample/build.gradle.kts | 3 +- .../speakers/presentation/SpeakerAdaptive.kt | 27 +++++++++-------- .../speakers/speakers-sample/build.gradle.kts | 3 +- gradle/libs.versions.toml | 19 ++++++------ style/components/adaptive/build.gradle.kts | 29 +++++++++++++++---- .../adaptive/BackHandler.android.kt | 8 +++++ .../style/components/adaptive/BackHandler.kt | 9 ++++++ .../components/adaptive/WindowSizeClassExt.kt | 0 .../components/adaptive/BackHandler.wasmJs.kt | 8 +++++ 14 files changed, 91 insertions(+), 45 deletions(-) rename features/partners/partners-presentation/src/{androidMain => commonMain}/kotlin/com/paligot/confily/partners/presentation/PartnersAdaptive.kt (81%) rename features/schedules/schedules-presentation/src/{androidMain => commonMain}/kotlin/com/paligot/confily/schedules/presentation/ScheduleGridAdaptive.kt (100%) rename features/speakers/speakers-presentation/src/{androidMain => commonMain}/kotlin/com/paligot/confily/speakers/presentation/SpeakerAdaptive.kt (79%) create mode 100644 style/components/adaptive/src/androidMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.android.kt create mode 100644 style/components/adaptive/src/commonMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.kt rename style/components/adaptive/src/{main => commonMain}/kotlin/com/paligot/confily/style/components/adaptive/WindowSizeClassExt.kt (100%) create mode 100644 style/components/adaptive/src/wasmJsMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.wasmJs.kt diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index fd6c0497c..9c151e206 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -86,10 +86,10 @@ dependencies { implementation(libs.androidx.appcompat) implementation(libs.androidx.browser) - implementation(platform(libs.androidx.compose.bom)) - implementation(libs.androidx.compose.material3.windowsizeclass) + implementation(libs.jetbrains.compose.material3.windowsizeclass) implementation(compose.ui) implementation(compose.components.resources) + implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.activity.compose) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.profile) diff --git a/build-logic/plugins/src/main/kotlin/conventions/PresentationLibraryPlugin.kt b/build-logic/plugins/src/main/kotlin/conventions/PresentationLibraryPlugin.kt index 4d38df0ae..cdeb32b4f 100644 --- a/build-logic/plugins/src/main/kotlin/conventions/PresentationLibraryPlugin.kt +++ b/build-logic/plugins/src/main/kotlin/conventions/PresentationLibraryPlugin.kt @@ -27,18 +27,14 @@ class PresentationLibraryPlugin: Plugin { browser() } sourceSets.commonMain.dependencies { + implementation(project(":style:components:adaptive")) implementation(compose.dependencies.material3) + implementation(libs.findBundle("jetbrains-compose-adaptive").get()) implementation(libs.findLibrary("jetbrains-kotlinx-collections").get()) implementation(libs.findLibrary("jetbrains-lifecycle-viewmodel-compose").get()) implementation(libs.findLibrary("koin-compose-viewmodel").get()) } sourceSets.androidMain.dependencies { - implementation(project(":style:components:adaptive")) - - implementation(project.dependencies.platform(libs.findLibrary("androidx-compose-bom").get())) - implementation(libs.findLibrary("androidx-compose-material3-windowsizeclass").get()) - implementation(libs.findBundle("androidx-compose-adaptive").get()) - implementation(libs.findLibrary("androidx-activity-compose").get()) implementation(libs.findLibrary("androidx-navigation-compose").get()) implementation(project.dependencies.platform(libs.findLibrary("google-firebase-bom").get())) diff --git a/features/main/main/build.gradle.kts b/features/main/main/build.gradle.kts index 939d73763..114eaf19b 100644 --- a/features/main/main/build.gradle.kts +++ b/features/main/main/build.gradle.kts @@ -27,9 +27,8 @@ dependencies { implementation(libs.koin.androidx.compose) + implementation(libs.bundles.jetbrains.compose.adaptive) implementation(platform(libs.androidx.compose.bom)) - implementation(libs.androidx.compose.material3.windowsizeclass) - implementation(libs.bundles.androidx.compose.adaptive) implementation(libs.androidx.compose.material3.adaptive.navigation.suite) implementation(libs.androidx.compose.runtime.livedata) implementation(compose.material3) diff --git a/features/partners/partners-presentation/src/androidMain/kotlin/com/paligot/confily/partners/presentation/PartnersAdaptive.kt b/features/partners/partners-presentation/src/commonMain/kotlin/com/paligot/confily/partners/presentation/PartnersAdaptive.kt similarity index 81% rename from features/partners/partners-presentation/src/androidMain/kotlin/com/paligot/confily/partners/presentation/PartnersAdaptive.kt rename to features/partners/partners-presentation/src/commonMain/kotlin/com/paligot/confily/partners/presentation/PartnersAdaptive.kt index 96ade4217..34dbff784 100644 --- a/features/partners/partners-presentation/src/androidMain/kotlin/com/paligot/confily/partners/presentation/PartnersAdaptive.kt +++ b/features/partners/partners-presentation/src/commonMain/kotlin/com/paligot/confily/partners/presentation/PartnersAdaptive.kt @@ -1,6 +1,5 @@ package com.paligot.confily.partners.presentation -import androidx.activity.compose.BackHandler import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @@ -11,7 +10,10 @@ import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import com.paligot.confily.style.components.adaptive.BackHandler +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable @@ -22,10 +24,11 @@ fun PartnersAdaptive( modifier: Modifier = Modifier, state: LazyGridState = rememberLazyGridState() ) { + val scope = rememberCoroutineScope() val scaffoldDirective = calculatePaneScaffoldDirective(currentWindowAdaptiveInfo()) val navigator = rememberListDetailPaneScaffoldNavigator(scaffoldDirective) BackHandler(navigator.canNavigateBack()) { - navigator.navigateBack() + scope.launch { navigator.navigateBack() } } ListDetailPaneScaffold( directive = navigator.scaffoldDirective, @@ -35,14 +38,16 @@ fun PartnersAdaptive( AnimatedPane { PartnersGridVM( onPartnerClick = { - navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, content = it) + scope.launch { + navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, contentKey = it) + } }, state = state ) } }, detailPane = { - navigator.currentDestination?.content?.let { + navigator.currentDestination?.contentKey?.let { AnimatedPane { PartnerDetailVM( partnerId = it, @@ -52,7 +57,7 @@ fun PartnersAdaptive( @Composable { Back { if (navigator.canNavigateBack()) { - navigator.navigateBack() + scope.launch { navigator.navigateBack() } } } } diff --git a/features/schedules/schedules-presentation/src/androidMain/kotlin/com/paligot/confily/schedules/presentation/ScheduleGridAdaptive.kt b/features/schedules/schedules-presentation/src/commonMain/kotlin/com/paligot/confily/schedules/presentation/ScheduleGridAdaptive.kt similarity index 100% rename from features/schedules/schedules-presentation/src/androidMain/kotlin/com/paligot/confily/schedules/presentation/ScheduleGridAdaptive.kt rename to features/schedules/schedules-presentation/src/commonMain/kotlin/com/paligot/confily/schedules/presentation/ScheduleGridAdaptive.kt diff --git a/features/schedules/schedules-sample/build.gradle.kts b/features/schedules/schedules-sample/build.gradle.kts index f720e7975..625e8ee80 100644 --- a/features/schedules/schedules-sample/build.gradle.kts +++ b/features/schedules/schedules-sample/build.gradle.kts @@ -34,8 +34,7 @@ dependencies { implementation(platform(libs.androidx.compose.bom)) implementation(compose.material3) - implementation(libs.androidx.compose.material3.windowsizeclass) - implementation(libs.bundles.androidx.compose.adaptive) + implementation(libs.bundles.jetbrains.compose.adaptive) implementation(libs.androidx.activity.compose) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.workmanager.ktx) diff --git a/features/speakers/speakers-presentation/src/androidMain/kotlin/com/paligot/confily/speakers/presentation/SpeakerAdaptive.kt b/features/speakers/speakers-presentation/src/commonMain/kotlin/com/paligot/confily/speakers/presentation/SpeakerAdaptive.kt similarity index 79% rename from features/speakers/speakers-presentation/src/androidMain/kotlin/com/paligot/confily/speakers/presentation/SpeakerAdaptive.kt rename to features/speakers/speakers-presentation/src/commonMain/kotlin/com/paligot/confily/speakers/presentation/SpeakerAdaptive.kt index 2f62d5598..421d7d5c6 100644 --- a/features/speakers/speakers-presentation/src/androidMain/kotlin/com/paligot/confily/speakers/presentation/SpeakerAdaptive.kt +++ b/features/speakers/speakers-presentation/src/commonMain/kotlin/com/paligot/confily/speakers/presentation/SpeakerAdaptive.kt @@ -1,6 +1,5 @@ package com.paligot.confily.speakers.presentation -import androidx.activity.compose.BackHandler import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @@ -11,7 +10,10 @@ import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import com.paligot.confily.style.components.adaptive.BackHandler +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable @@ -22,27 +24,28 @@ fun SpeakerAdaptive( modifier: Modifier = Modifier, state: LazyGridState = rememberLazyGridState() ) { + val scope = rememberCoroutineScope() val scaffoldDirective = calculatePaneScaffoldDirective(currentWindowAdaptiveInfo()) val navigator = rememberListDetailPaneScaffoldNavigator(scaffoldDirective) BackHandler(navigator.canNavigateBack()) { - navigator.navigateBack() + scope.launch { navigator.navigateBack() } } ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, modifier = modifier, listPane = { - AnimatedPane { - SpeakersGridVM( - onSpeakerClicked = { - navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, content = it) - }, - state = state - ) - } + SpeakersGridVM( + onSpeakerClicked = { + scope.launch { + navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, contentKey = it) + } + }, + state = state + ) }, detailPane = { - navigator.currentDestination?.content?.let { + navigator.currentDestination?.contentKey?.let { AnimatedPane { SpeakerDetailVM( speakerId = it, @@ -52,7 +55,7 @@ fun SpeakerAdaptive( @Composable { Back { if (navigator.canNavigateBack()) { - navigator.navigateBack() + scope.launch { navigator.navigateBack() } } } } diff --git a/features/speakers/speakers-sample/build.gradle.kts b/features/speakers/speakers-sample/build.gradle.kts index ab1903d4d..e230de598 100644 --- a/features/speakers/speakers-sample/build.gradle.kts +++ b/features/speakers/speakers-sample/build.gradle.kts @@ -32,10 +32,9 @@ dependencies { implementation(libs.androidx.appcompat) + implementation(libs.bundles.jetbrains.compose.adaptive) implementation(platform(libs.androidx.compose.bom)) implementation(compose.material3) - implementation(libs.androidx.compose.material3.windowsizeclass) - implementation(libs.bundles.androidx.compose.adaptive) implementation(libs.androidx.activity.compose) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.workmanager.ktx) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1afbd5d23..36e6e0ed4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,6 @@ androidx-benchmark = "1.3.3" androidx-browser = "1.8.0" androidx-camera = "1.4.0" androidx-compose-bom = "2024.11.00" -androidx-compose-adaptive = "1.0.0" androidx-compose-adaptive-navigation = "1.3.1" androidx-espresso = "3.6.1" androidx-glance = "1.1.1" @@ -47,6 +46,7 @@ google-services = "4.4.2" google-services-wearable = "19.0.0" google-zxing = "3.5.3" jetbrains-compose = "1.7.1" +jetbrains-compose-adaptive = "1.1.0-alpha01" jetbrains-lifecycle = "2.8.0" jetbrains-kotlin = "2.1.0" jetbrains-kotlinx-browser = "0.3" @@ -81,10 +81,6 @@ androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycl androidx-camera-view = { group = "androidx.camera", name = "camera-view", version.ref = "androidx-camera" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidx-compose-bom" } androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } -androidx-compose-material3-windowsizeclass = { group = "androidx.compose.material3", name = "material3-window-size-class" } -androidx-compose-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive", version.ref = "androidx-compose-adaptive" } -androidx-compose-material3-adaptive-layout = { group = "androidx.compose.material3.adaptive", name = "adaptive-layout", version.ref = "androidx-compose-adaptive" } -androidx-compose-material3-adaptive-navigation = { group = "androidx.compose.material3.adaptive", name = "adaptive-navigation", version.ref = "androidx-compose-adaptive" } androidx-compose-material3-adaptive-navigation-suite = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite", version.ref = "androidx-compose-adaptive-navigation" } androidx-compose-runtime-livedata = { group = "androidx.compose.runtime", name = "runtime-livedata" } androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "androidx-splashscreen" } @@ -128,6 +124,10 @@ detekt-gradlePlugin = { group = "io.gitlab.arturbosch.detekt", name = "detekt-gr jetbrains-compose-gradlePlugin = { group = "org.jetbrains.compose", name = "compose-gradle-plugin", version.ref = "jetbrains-compose" } jetbrains-compose-compiler-gradlePlugin = { group = "org.jetbrains.kotlin", name = "compose-compiler-gradle-plugin", version.ref = "jetbrains-kotlin" } +jetbrains-compose-material3-adaptive = { group = "org.jetbrains.compose.material3.adaptive", name = "adaptive", version.ref = "jetbrains-compose-adaptive" } +jetbrains-compose-material3-adaptive-layout = { group = "org.jetbrains.compose.material3.adaptive", name = "adaptive-layout", version.ref = "jetbrains-compose-adaptive" } +jetbrains-compose-material3-adaptive-navigation = { group = "org.jetbrains.compose.material3.adaptive", name = "adaptive-navigation", version.ref = "jetbrains-compose-adaptive" } +jetbrains-compose-material3-windowsizeclass = { group = "org.jetbrains.compose.material3", name = "material3-window-size-class", version.ref = "jetbrains-compose" } jetbrains-lifecycle-viewmodel-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "jetbrains-lifecycle" } jetbrains-kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "jetbrains-kotlin" } jetbrains-kotlin-serialization-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-serialization", version.ref = "jetbrains-kotlin" } @@ -212,10 +212,11 @@ squareup-okio = { group = "com.squareup.okio", name = "okio", version.ref = "squ zxing-android-embedded = { group = "com.journeyapps", name = "zxing-android-embedded", version.ref = "zxing-android-embedded" } [bundles] -androidx-compose-adaptive = [ - "androidx-compose-material3-adaptive", - "androidx-compose-material3-adaptive-layout", - "androidx-compose-material3-adaptive-navigation" +jetbrains-compose-adaptive = [ + "jetbrains-compose-material3-adaptive", + "jetbrains-compose-material3-adaptive-layout", + "jetbrains-compose-material3-adaptive-navigation", + "jetbrains-compose-material3-windowsizeclass" ] androidx-glance = [ "androidx-glance-appwidget", diff --git a/style/components/adaptive/build.gradle.kts b/style/components/adaptive/build.gradle.kts index 14a0edcef..28a5ee819 100644 --- a/style/components/adaptive/build.gradle.kts +++ b/style/components/adaptive/build.gradle.kts @@ -1,5 +1,7 @@ +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl + plugins { - id("confily.android.library") + id("confily.multiplatform.library") id("confily.android.library.compose") id("confily.quality") } @@ -8,8 +10,25 @@ android { namespace = "com.paligot.confily.style.components.adaptive" } -dependencies { - implementation(platform(libs.androidx.compose.bom)) - implementation(libs.bundles.androidx.compose.adaptive) - implementation(libs.androidx.compose.material3.windowsizeclass) +kotlin { + androidTarget() + + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + useCommonJs() + browser() + } + + sourceSets { + val commonMain by getting { + dependencies { + implementation(libs.bundles.jetbrains.compose.adaptive) + } + } + val androidMain by getting { + dependencies { + implementation(libs.androidx.activity.compose) + } + } + } } diff --git a/style/components/adaptive/src/androidMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.android.kt b/style/components/adaptive/src/androidMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.android.kt new file mode 100644 index 000000000..5eed2cc38 --- /dev/null +++ b/style/components/adaptive/src/androidMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.android.kt @@ -0,0 +1,8 @@ +package com.paligot.confily.style.components.adaptive + +import androidx.compose.runtime.Composable + +@Composable +actual fun BackHandler(enabled: Boolean, onBack: () -> Unit) { + androidx.activity.compose.BackHandler(enabled = enabled, onBack = onBack) +} diff --git a/style/components/adaptive/src/commonMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.kt b/style/components/adaptive/src/commonMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.kt new file mode 100644 index 000000000..6ea1f7064 --- /dev/null +++ b/style/components/adaptive/src/commonMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.kt @@ -0,0 +1,9 @@ +package com.paligot.confily.style.components.adaptive + +import androidx.compose.runtime.Composable + +@Composable +expect fun BackHandler( + enabled: Boolean = true, + onBack: () -> Unit +) diff --git a/style/components/adaptive/src/main/kotlin/com/paligot/confily/style/components/adaptive/WindowSizeClassExt.kt b/style/components/adaptive/src/commonMain/kotlin/com/paligot/confily/style/components/adaptive/WindowSizeClassExt.kt similarity index 100% rename from style/components/adaptive/src/main/kotlin/com/paligot/confily/style/components/adaptive/WindowSizeClassExt.kt rename to style/components/adaptive/src/commonMain/kotlin/com/paligot/confily/style/components/adaptive/WindowSizeClassExt.kt diff --git a/style/components/adaptive/src/wasmJsMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.wasmJs.kt b/style/components/adaptive/src/wasmJsMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.wasmJs.kt new file mode 100644 index 000000000..f88cd2a87 --- /dev/null +++ b/style/components/adaptive/src/wasmJsMain/kotlin/com/paligot/confily/style/components/adaptive/BackHandler.wasmJs.kt @@ -0,0 +1,8 @@ +package com.paligot.confily.style.components.adaptive + +import androidx.compose.runtime.Composable + +@Composable +actual fun BackHandler(enabled: Boolean, onBack: () -> Unit) { + // no-op +}