From db024805713ef1ccc4772dd72c53582cc0ec6e3b Mon Sep 17 00:00:00 2001 From: skydoves Date: Thu, 12 Sep 2024 09:26:15 +0900 Subject: [PATCH 1/2] Support withWasmJs for coil3 --- .../main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt b/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt index f30d0320..8ffbfedb 100644 --- a/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt +++ b/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt @@ -78,6 +78,7 @@ internal fun Project.configureComposeMultiplatform( } } withJs() + withWasmJs() } } } From 1adb9b006772d99d6b2b30269e0f961bebf4ec3c Mon Sep 17 00:00:00 2001 From: skydoves Date: Thu, 12 Sep 2024 09:45:59 +0900 Subject: [PATCH 2/2] Use Ktor3 and support Wasm for coil3 --- .../github/skydoves/landscapistdemo/App.kt | 5 +- .../skydoves/benchmark/landscapist/app/App.kt | 2 +- build-logic/convention/build.gradle.kts | 4 + ...ultiplatformWasmLibraryConventionPlugin.kt | 58 ++++++++++ .../landscapist/ComposeMultiplatform.kt | 19 ++-- .../landscapist/ComposeMultiplatformWasm.kt | 105 ++++++++++++++++++ coil3/build.gradle.kts | 4 +- .../landscapist/coil3/LocalCoilProvider.kt | 2 +- gradle/libs.versions.toml | 2 +- landscapist-animation/build.gradle.kts | 2 +- landscapist-placeholder/build.gradle.kts | 2 +- landscapist/build.gradle.kts | 2 +- 12 files changed, 189 insertions(+), 18 deletions(-) create mode 100644 build-logic/convention/src/main/kotlin/ComposeMultiplatformWasmLibraryConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatformWasm.kt diff --git a/app/src/main/kotlin/com/github/skydoves/landscapistdemo/App.kt b/app/src/main/kotlin/com/github/skydoves/landscapistdemo/App.kt index 417e1cb0..7bceba4c 100644 --- a/app/src/main/kotlin/com/github/skydoves/landscapistdemo/App.kt +++ b/app/src/main/kotlin/com/github/skydoves/landscapistdemo/App.kt @@ -21,9 +21,10 @@ import android.content.Context import androidx.multidex.MultiDexApplication import coil3.ImageLoader import coil3.SingletonImageLoader -import coil3.network.ktor2.KtorNetworkFetcherFactory +import coil3.network.ktor3.KtorNetworkFetcherFactory import com.facebook.drawee.backends.pipeline.Fresco import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory +import com.facebook.imagepipeline.core.DownsampleMode import dagger.hilt.android.HiltAndroidApp import okhttp3.OkHttpClient @@ -38,7 +39,7 @@ class App : MultiDexApplication(), SingletonImageLoader.Factory { OkHttpImagePipelineConfigFactory .newBuilder(this, OkHttpClient.Builder().build()) .setDiskCacheEnabled(true) - .setDownsampleEnabled(true) + .setDownsampleMode(DownsampleMode.AUTO) .setResizeAndRotateEnabledForNetwork(true) .build() diff --git a/benchmark-landscapist-app/src/main/kotlin/com/skydoves/benchmark/landscapist/app/App.kt b/benchmark-landscapist-app/src/main/kotlin/com/skydoves/benchmark/landscapist/app/App.kt index 79b9975a..5f4449de 100644 --- a/benchmark-landscapist-app/src/main/kotlin/com/skydoves/benchmark/landscapist/app/App.kt +++ b/benchmark-landscapist-app/src/main/kotlin/com/skydoves/benchmark/landscapist/app/App.kt @@ -21,7 +21,7 @@ import android.app.Application import android.content.Context import coil3.ImageLoader import coil3.SingletonImageLoader -import coil3.network.ktor2.KtorNetworkFetcherFactory +import coil3.network.ktor3.KtorNetworkFetcherFactory import com.facebook.drawee.backends.pipeline.Fresco import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory import com.facebook.imagepipeline.core.DownsampleMode diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 313b0777..f81adffb 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -30,6 +30,10 @@ gradlePlugin { id = "landscapist.library.compose.multiplatform" implementationClass = "ComposeMultiplatformLibraryConventionPlugin" } + register("composeMultiplatformWasmLibrary") { + id = "landscapist.library.compose.multiplatformWasm" + implementationClass = "ComposeMultiplatformWasmLibraryConventionPlugin" + } register("spotless") { id = "landscapist.spotless" implementationClass = "SpotlessConventionPlugin" diff --git a/build-logic/convention/src/main/kotlin/ComposeMultiplatformWasmLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/ComposeMultiplatformWasmLibraryConventionPlugin.kt new file mode 100644 index 00000000..34118c73 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/ComposeMultiplatformWasmLibraryConventionPlugin.kt @@ -0,0 +1,58 @@ +/* + * Designed and developed by 2020-2022 skydoves (Jaewoong Eum) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.android.build.gradle.LibraryExtension +import com.skydoves.landscapist.configureAndroidCompose +import com.skydoves.landscapist.configureComposeMultiplatform +import com.skydoves.landscapist.configureKotlinAndroid +import com.skydoves.landscapist.kotlinOptions +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.getByType +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension + +class ComposeMultiplatformWasmLibraryConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + pluginManager.apply("com.android.library") + pluginManager.apply("org.jetbrains.kotlin.multiplatform") + pluginManager.apply("org.jetbrains.compose") + pluginManager.apply("com.vanniktech.maven.publish") + pluginManager.apply("binary-compatibility-validator") + pluginManager.apply("androidx.baselineprofile") + + extensions.configure libraryExtension@{ + extensions.configure kmpExtension@{ + configureComposeMultiplatform(this@libraryExtension, this@kmpExtension) + } + } + + val libs = extensions.getByType().named("libs") + tasks.withType(JavaCompile::class.java).configureEach { + this.targetCompatibility = libs.findVersion("jvmTarget").get().toString() + this.sourceCompatibility = libs.findVersion("jvmTarget").get().toString() + } + + dependencies { + add("baselineProfile", project(":benchmark-landscapist")) + } + } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt b/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt index 8ffbfedb..153469dc 100644 --- a/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt +++ b/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatform.kt @@ -38,14 +38,18 @@ internal fun Project.configureComposeMultiplatform( androidTarget { publishLibraryVariants("release") } jvm("desktop") - js { - browser() - nodejs() - binaries.executable() - binaries.library() - } + @OptIn(ExperimentalWasmDsl::class) wasmJs { - binaries.executable() + browser { + testTask { + enabled = false + } + } + nodejs { + testTask { + enabled = false + } + } binaries.library() } @@ -78,7 +82,6 @@ internal fun Project.configureComposeMultiplatform( } } withJs() - withWasmJs() } } } diff --git a/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatformWasm.kt b/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatformWasm.kt new file mode 100644 index 00000000..7bb05a6a --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/skydoves/landscapist/ComposeMultiplatformWasm.kt @@ -0,0 +1,105 @@ +/* + * Designed and developed by 2020-2022 skydoves (Jaewoong Eum) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("UnstableApiUsage") + +package com.skydoves.landscapist + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.kotlin.dsl.invoke +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl + +/** + * Configure Compose-Multiplatform-specific options + */ +internal fun Project.configureComposeMultiplatformWasm( + commonExtension: CommonExtension<*, *, *, *, *, *>, + kotlinMultiplatformExtension: KotlinMultiplatformExtension, +) { + pluginManager.apply("org.jetbrains.kotlin.plugin.compose") + + kotlinMultiplatformExtension.apply { + androidTarget { publishLibraryVariants("release") } + jvm("desktop") + + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + browser { + testTask { + enabled = false + } + } + nodejs { + testTask { + enabled = false + } + } + binaries.library() + } + + iosX64() + iosArm64() + iosSimulatorArm64() + + macosX64() + macosArm64() + + @Suppress("OPT_IN_USAGE") + applyHierarchyTemplate { + common { + group("jvm") { + withAndroidTarget() + withJvm() + } + group("skia") { + withJvm() + group("darwin") { + group("apple") { + group("ios") { + withIosX64() + withIosArm64() + withIosSimulatorArm64() + } + group("macos") { + withMacosX64() + withMacosArm64() + } + } + withJs() + withWasmJs() + } + } + } + } + + explicitApi() + } + + commonExtension.apply { + buildFeatures { + compose = true + } + + packaging { + resources { + excludes.add("/META-INF/{AL2.0,LGPL2.1}") + } + } + } +} diff --git a/coil3/build.gradle.kts b/coil3/build.gradle.kts index 19adca19..a0e1d3db 100644 --- a/coil3/build.gradle.kts +++ b/coil3/build.gradle.kts @@ -16,7 +16,7 @@ import com.github.skydoves.landscapist.Configuration plugins { - id("landscapist.library.compose.multiplatform") + id("landscapist.library.compose.multiplatformWasm") id("landscapist.spotless") } @@ -47,7 +47,7 @@ kotlin { dependencies { api(project(":landscapist")) api(libs.coil3) - api(libs.coil3.network.ktor2) + api(libs.coil3.network.ktor3) api(libs.ktor.core) implementation(compose.ui) diff --git a/coil3/src/commonMain/kotlin/com/skydoves/landscapist/coil3/LocalCoilProvider.kt b/coil3/src/commonMain/kotlin/com/skydoves/landscapist/coil3/LocalCoilProvider.kt index b077dea3..136d1e7e 100644 --- a/coil3/src/commonMain/kotlin/com/skydoves/landscapist/coil3/LocalCoilProvider.kt +++ b/coil3/src/commonMain/kotlin/com/skydoves/landscapist/coil3/LocalCoilProvider.kt @@ -20,7 +20,7 @@ import androidx.compose.runtime.ProvidableCompositionLocal import androidx.compose.runtime.staticCompositionLocalOf import coil3.ImageLoader import coil3.SingletonImageLoader -import coil3.network.ktor2.KtorNetworkFetcherFactory +import coil3.network.ktor3.KtorNetworkFetcherFactory /** * Local containing the preferred [ImageLoader] for providing the same instance diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e59e27a9..0a03ddd4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ glide = "4.16.0" fresco = "3.2.0" coil = "2.7.0" coil3 = "3.0.0-alpha10" -ktor = "2.3.12" +ktor = "3.0.0-rc-1" palette = "3.1.0" hilt = "2.52" spotless = "6.21.0" diff --git a/landscapist-animation/build.gradle.kts b/landscapist-animation/build.gradle.kts index 2547c852..326eb823 100644 --- a/landscapist-animation/build.gradle.kts +++ b/landscapist-animation/build.gradle.kts @@ -16,7 +16,7 @@ import com.github.skydoves.landscapist.Configuration plugins { - id("landscapist.library.compose.multiplatform") + id("landscapist.library.compose.multiplatformWasm") id("landscapist.spotless") } diff --git a/landscapist-placeholder/build.gradle.kts b/landscapist-placeholder/build.gradle.kts index 7d255547..48e2c97f 100644 --- a/landscapist-placeholder/build.gradle.kts +++ b/landscapist-placeholder/build.gradle.kts @@ -16,7 +16,7 @@ import com.github.skydoves.landscapist.Configuration plugins { - id("landscapist.library.compose.multiplatform") + id("landscapist.library.compose.multiplatformWasm") id("landscapist.spotless") } diff --git a/landscapist/build.gradle.kts b/landscapist/build.gradle.kts index 6cadcf04..47e65d76 100644 --- a/landscapist/build.gradle.kts +++ b/landscapist/build.gradle.kts @@ -17,7 +17,7 @@ import com.github.skydoves.landscapist.Configuration plugins { - id("landscapist.library.compose.multiplatform") + id("landscapist.library.compose.multiplatformWasm") id("landscapist.spotless") }