coil-kt / coil

Image loading for Android and Compose Multiplatform.
https://coil-kt.github.io/coil/
Apache License 2.0
10.86k stars 668 forks source link

Compose Multiplatform support #842

Closed tiwiz closed 1 month ago

tiwiz commented 3 years ago

Is your feature request related to a problem? Please describe. As an Android Developer, I would love to use Coil with Compose Desktop in the same way I use Coil for Compose on Android.

Describe the solution you'd like Ideally, it would be the best to have the same approach we have on Android, so that the knowledge can be reused.

Additional context I think it would be OK to link the image download scope to either a LaunchedEffect in a Composable, or just link it to the Application lifecycle.

mahramane commented 6 months ago

3.0.0-beta-2-eap-932 is out and support wasm js. please update the ktor version in coil library.

artemyto commented 6 months ago

3.0.0-beta-2-eap-932 is out and support wasm js. please update the ktor version in coil library.

This version is not on Maven Central, but is from different repository (KtorEAP)

sivansundar commented 6 months ago

For some reason Im not able to load images despite using the right versions and dependencies.

Using the following under my commonMain :

implementation("io.coil-kt.coil3:coil-compose:3.0.0-alpha06")
implementation("io.coil-kt.coil3:coil-network-ktor:3.0.0-alpha06")
implementation("io.ktor:ktor-client-core:3.0.0-wasm2")

Composable :

 AsyncImage(
        modifier = Modifier.wrapContentSize(),
        model = item.imageUrl,
        contentDescription = "",
        error = painterResource(resource = Res.drawable.compose_multiplatform)
)

Not sure if I am missing something very basic.

DRSchlaubi commented 6 months ago

For some reason Im not able to load images despite using the right versions and dependencies.

Using the following under my commonMain :

implementation("io.coil-kt.coil3:coil-compose:3.0.0-alpha06")
implementation("io.coil-kt.coil3:coil-network-ktor:3.0.0-alpha06")
implementation("io.ktor:ktor-client-core:3.0.0-wasm2")

Composable :

 AsyncImage(
        modifier = Modifier.wrapContentSize(),
        model = item.imageUrl,
        contentDescription = "",
        error = painterResource(resource = Res.drawable.compose_multiplatform)
)

Not sure if I am missing something very basic.

Might want to share some error?

sivansundar commented 6 months ago

Sorry about that.

🚨 Failed - <IMAGEURL> - java.lang.ExceptionInInitializerError
2024-05-29 21:28:31.009  7146-7146  RealImageLoader         dev.sivan.muncheese                  I  🚨 Failed - <IMAGEURL> - java.lang.NoClassDefFoundError: <clinit> failed for class io.ktor.client.HttpClientJvmKt; see exception in other thread
2024-05-29 21:28:31.009  7146-7146  RealImageLoader         dev.sivan.muncheese                  I  🚨 Failed - <IMAGEURL> - java.lang.NoClassDefFoundError: io.ktor.client.HttpClientJvmKt
2024-05-29 21:28:31.009  7146-7146  RealImageLoader         dev.sivan.muncheese                  I  🚨 Failed - <IMAGEURL> - java.lang.NoClassDefFoundError: io.ktor.client.HttpClientJvmKt
DRSchlaubi commented 6 months ago

Sorry about that.

🚨 Failed - <IMAGEURL> - java.lang.ExceptionInInitializerError
2024-05-29 21:28:31.009  7146-7146  RealImageLoader         dev.sivan.muncheese                  I  🚨 Failed - <IMAGEURL> - java.lang.NoClassDefFoundError: <clinit> failed for class io.ktor.client.HttpClientJvmKt; see exception in other thread
2024-05-29 21:28:31.009  7146-7146  RealImageLoader         dev.sivan.muncheese                  I  🚨 Failed - <IMAGEURL> - java.lang.NoClassDefFoundError: io.ktor.client.HttpClientJvmKt
2024-05-29 21:28:31.009  7146-7146  RealImageLoader         dev.sivan.muncheese                  I  🚨 Failed - <IMAGEURL> - java.lang.NoClassDefFoundError: io.ktor.client.HttpClientJvmKt

Are you using proguard by chance?

sivansundar commented 6 months ago

No.

sivansundar commented 6 months ago

Alright I made it work. Missed adding ktor clients to all the platforms. Now my dependencies looks like this :

        commonMain.dependencies {
            implementation("io.coil-kt.coil3:coil:3.0.0-alpha06")
            implementation("io.coil-kt.coil3:coil-compose:3.0.0-alpha06")
            implementation("io.coil-kt.coil3:coil-network-ktor:3.0.0-alpha06")

            implementation("io.ktor:ktor-client-core:3.0.0-wasm2")
        }

        androidMain.dependencies {
            implementation("io.coil-kt.coil3:coil-network-okhttp:3.0.0-alpha06")

        }

        desktopMain.dependencies {
            implementation(compose.desktop.currentOs)
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing")
            implementation("io.coil-kt.coil3:coil-network-okhttp:3.0.0-alpha06")

        }

        iosMain.dependencies {
            implementation("io.ktor:ktor-client-darwin:3.0.0-wasm2")
        }

        wasmJsMain.dependencies {
            implementation("io.ktor:ktor-client-js:3.0.0-wasm2")
        }
Feinate commented 5 months ago

How to use png file from composeResources with coil... Seems to be impossible, lack of documentation...

Holetzky commented 4 months ago

Alright I made it work. Missed adding ktor clients to all the platforms. Now my dependencies looks like this :

        commonMain.dependencies {
            implementation("io.coil-kt.coil3:coil:3.0.0-alpha06")
            implementation("io.coil-kt.coil3:coil-compose:3.0.0-alpha06")
            implementation("io.coil-kt.coil3:coil-network-ktor:3.0.0-alpha06")

            implementation("io.ktor:ktor-client-core:3.0.0-wasm2")
        }

        androidMain.dependencies {
            implementation("io.coil-kt.coil3:coil-network-okhttp:3.0.0-alpha06")

        }

        desktopMain.dependencies {
            implementation(compose.desktop.currentOs)
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing")
            implementation("io.coil-kt.coil3:coil-network-okhttp:3.0.0-alpha06")

        }

        iosMain.dependencies {
            implementation("io.ktor:ktor-client-darwin:3.0.0-wasm2")
        }

        wasmJsMain.dependencies {
            implementation("io.ktor:ktor-client-js:3.0.0-wasm2")
        }

Thank you for sharing. To resolve ktor client with wasm2, I needed to add experimental jetbrains space to my settings.gradle.kts. Maybe that helps someone else:

dependencyResolutionManagement {
    repositories {
        google {
            mavenContent {
                includeGroupAndSubgroups("androidx")
                includeGroupAndSubgroups("com.android")
                includeGroupAndSubgroups("com.google")
            }
        }
        mavenCentral()
        maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
        maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental")
    }
}
ColtonIdle commented 4 months ago

One liner for compose multiplatform https://github.com/alexstyl/addcoilmultiplatform

skydoves commented 3 months ago

Landscapist also supports KMP with coil3.

sourceSets {
    val commonMain by getting {
        dependencies {
            implementation("com.github.skydoves:landscapist-coil3:2.3.6")
        }
    }
}
joreilly commented 2 months ago

Hopefully this is ok place to post this but has anyone come across error like this when using Coil3 in a Wasm based Compose for Web client? Seeing this currently in the PeopleInSpace sample. Using Coil 3.0.0-alpha10 and Ktor 3.0.0-rc-1

illegal cast
RuntimeError: illegal cast
    at <com.example:compose-web>.coil3.network.ktor.internal.KtorNetworkResponseBody__close-impl (http://localhost:8080/peopleinspace.wasm:wasm-function[67145]:0x8f8ac0)
    at <com.example:compose-web>.coil3.network.ktor.internal.KtorNetworkResponseBody.close (http://localhost:8080/peopleinspace.wasm:wasm-function[67151]:0x8f8bee)
    at <com.example:compose-web>.kotlin.closeFinally (http://localhost:8080/peopleinspace.wasm:wasm-function[7234]:0x413c78)
    at <com.example:compose-web>.coil3.network.internal.$readBufferCOROUTINE$3.doResume (http://localhost:8080/peopleinspace.wasm:wasm-function[63020]:0x8a71ef)
    at <com.example:compose-web>.coil3.network.internal.readBuffer (http://localhost:8080/peopleinspace.wasm:wasm-function[63015]:0x8a6ddd)
    at <com.example:compose-web>.coil3.network.NetworkFetcher$fetch$slambda.doResume (http://localhost:8080/peopleinspace.wasm:wasm-function[62948]:0x8a4d0d)
    at <com.example:compose-web>.coil3.network.NetworkFetcher$fetch$slambda.invoke (http://localhost:8080/peopleinspace.wasm:wasm-function[62946]:0x8a4aae)
    at <com.example:compose-web>.coil3.network.NetworkFetcher$fetch$slambda.invoke (http://localhost:8080/peopleinspace.wasm:wasm-function[62947]:0x8a4adc)
    at <com.example:compose-web>.coil3.network.NetworkFetcher$executeNetworkRequest$slambda.doResume (http://localhost:8080/peopleinspace.wasm:wasm-function[62960]:0x8a5244)
    at <com.example:compose-web>.coil3.network.NetworkFetcher$executeNetworkRequest$slambda.invoke (http://localhost:8080/peopleinspace.wasm:wasm-function[62958]:0x8a5138)
colinrtwhite commented 2 months ago

@joreilly Can you try with the latest snapshot in ~2 hours once it publishes? I just bumped main to Ktor 3.0.0-rc-1, which might fix it.

EDIT: Actually looks like you might be using an older version of the Coil Ktor dependency? The stack trace references coil3.network.ktor.internal, but io.coil-kt.coil3:coil-network-ktor3:3.0.0-alpha10 should have the package name coil3.network.ktor3.internal.

joreilly commented 2 months ago

@colinrtwhite ah, my bad, I messed up when updating to alpha10. Apologies for the confusion.

JacobCube commented 1 month ago

Coil version 3.0.0-alpha10 together with Ktor version 3.0.0-rc-1 is crashing for me on release Jvm. The same project works for debug build, so it must be something specific to obfuscation of Proguard.

java.lang.ClassFormatError: Invalid index 2 in LocalVariableTable in class file coil3/compose/internal/UtilsKt at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) at coil3.compose.AsyncImageKt.AsyncImage-76YX9Dk(AsyncImage.kt:161) at coil3.compose.AsyncImageKt.AsyncImage-QgsmV_s(AsyncImage.kt:132) at coil3.compose.SingletonAsyncImageKt.AsyncImage-gl8XCv8(SingletonAsyncImage.kt:125)

Even though my Proguard rules contain both -keep class coil3.** { *; } and for Ktor: -keep class io.ktor.client.** { *; } -keep class io.ktor.utils.io.** { *; } -keep class io.ktor.utils.io.jvm.** { *; } -keep class io.ktor.utils.io.nio.** { *; } -keep class io.ktor.server.config.** { *; } -keep class io.ktor.serialization.** { *; } '

EDIT: as a hotfix, adding -dontoptimize to Proguard rules seems t ofix the issue.

colinrtwhite commented 1 month ago

@JacobCube I would avoid adding -keep class coil3.** { *; } as that prevents all optimization, obfuscation, and minification of Coil's code. Compose code specifically really benefits from R8's optimization. For your error I'd recommend reporting it to the R8 issue tracker. You could also try using a different version of AGP as it usually bundles newer versions of R8 with fixes.

JacobCube commented 1 month ago

Thanks for the feedback, I'll change the rules. Regarding the R8, the issue occurs only with this library, so it's either some missing rule I thought you'd know of or some internal issue. Am I missing something? I'll report it to R8 nonetheless.

colinrtwhite commented 1 month ago

Hi folks, I'm going to close this issue now that Compose Multiplatform is fully supported in version 3.0.0-rc01. If you find bugs please open any new issues here. Thanks!