Closed tiwiz closed 1 month ago
~I agree this would be cool to have. That said, I think this is very very unlikely to be implemented as Coil heavily relies on a number of Android framework classes (Bitmap
, BitmapFactory
, ImageDecoder
) and integrates closely with View
s and Lifecycle
s. Also, Coil depends on a number of AndroidX libraries and OkHttp which aren't (and likely won't) be multiplatform. Overall, it's a lot of work and I don't have plans to work on it. Going to leave this open as a catch-all for multiplatform questions.~
Check here for an update. TLDR: This is now planned!
On compose
I wrapped coil and wrote two actual
functions. On desktop its look as
package components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import com.tradernet.data.source.getHttpClient
import io.ktor.client.request.*
import org.jetbrains.skija.Image
import androidx.compose.foundation.Image as ComposeImage
suspend fun loadPicture(url: String): Result<ImageBitmap> {
val client = getHttpClient()
return try {
val image = client.get<ByteArray>(url)
Result.success(Image.makeFromEncoded(image).asImageBitmap())
} catch (e: Exception) {
Result.failure(e)
}
}
@Composable
actual fun ExternalImage(url: String, modifier: Modifier, OnFail: @Composable () -> Unit) {
var isLoading by remember { mutableStateOf(false) }
var hasFail by remember { mutableStateOf(false) }
var imageBitmap: ImageBitmap? by remember { mutableStateOf(null) }
LaunchedEffect(url) {
isLoading = true
loadPicture(url)
.onSuccess {
imageBitmap = it
}
.onFailure {
hasFail = true
}
isLoading = false
}
when {
isLoading -> {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
CircularProgressIndicator()
}
}
hasFail -> {
OnFail()
}
else -> {
imageBitmap?.let { bitmap ->
ComposeImage(
bitmap = bitmap,
contentDescription = "",
contentScale = ContentScale.FillWidth,
alpha = DefaultAlpha,
colorFilter = null,
)
} ?: OnFail()
}
}
}
it's a variant I took from https://stackoverflow.com/questions/66002696/how-to-load-image-from-remote-url-in-kotlin-compose-desktop. What's missing is caching mechanism.
I too would love to see a coil-desktop implementation, even if it was just using JVM calls under the hood, similar to this post https://dev.to/gerardpaligot/sharing-compose-components-between-android-and-desktop-17kg
Thanks @jershell . Just a note for those who will try to reuse your snippet: it was easier for me to use skiko v0.5.3 instead of skija, and then just swap the line in the try catch with:
Result.success(Image.makeFromEncoded(image).toComposeImageBitmap())
Works but yikes for the caching indeed, so +1 for Coil-desktop. Not sure if there is multiplatform alternatives or even work-in-progress on this topic, please share if you know something.
In case it's relevant to the feasibility - https://github.com/square/okhttp/issues/6963
Libraries like Square Wire (gRPC) are also blocked on a multiplatform OkHttp Call.Factory. I hope in 2022, we get a good suite of KMP libraries for IO, Networking, RPC, Images, so hope this becomes feasible at some point.
For multiplatform projects there is the Kamel, based on watch I saw of the source code, almost all the source is based on Ktor Client
, Skiko
and Androidx Compose
, this meas that even now that is working on Desktop and don't see how hard would be to make it support on iOS in the future.
Hi, since coil 2.0 do you have any plans to implement this feature?
Porting the library from okhttp
to ktor
(which can still use okhttp) will be a great start to make this library multiplatform.
Coroutines, ktor and okio are all multiplatform libraries.
Adding ktor means adding more code in Android apps with no purpose. Either Coil stick to Android and it should not try to move to ktor (and keep a lightweight performant library), or it's decided that Coil wants to go full KMP. I think a lot of Android projects will not move to KMP right now, so Coil is still a very good option as is.
Since Kamel is going multi-platform from start, maybe better to consider adding missing things to Kamel instead of trying to port a lot of Android specific code to KMP?
This issue is for compose desktop which works on the jvm, not KMP, which I do think would be an easier ask.
I am using this library for now which works great: https://github.com/alialbaali/Kamel/pull/14#issuecomment-1150598198
Yes desktop (jvm) version would be great, all of infrastructure as far as coroutines, okhttp etc should be there, so "only" Bitmap
& friends would need to be wrapped
Compose has a ImageBitmap
, maybe that is a way?
Note that if you want to write a proper multiplatform (mac, win, linux) desktop app, youre option basically is just Electron (VS Code, Spotify, Slack, etc), which is ..not great performance.
I could see a world where compose desktop could be very popular.
You can use libs like https://github.com/alialbaali/Kamel or https://github.com/ltttttttttttt/load-the-image and use @jershell's idea to wrap this libs with expect/actual.
there is already an image loader that use coil as foundation to load images https://github.com/qdsfdhvh/compose-imageloader
Hi folks, big update! There are now plans to add Kotlin Multiplatform support to Coil and this will be the main feature of 3.x. I can't offer a timeline, but this is top of mind.
The plan is to leave Coil's public API largely the same (except for Android-specific classes) for an initial alpha then iterate on other public API changes we want to make for 3.x. Some of the main initial changes we'll need to make will be to abstract away usages of Bitmap
and Drawable
and replace BitmapFactory
with a multiplatform solution. Fortunately, Compose Multiplatform should make migrating the coil-compose
artifact fairly straightforward. I'm heading on holiday until May 7th, but will follow up with more details afterwards.
To be clear, by Kotlin Multiplatform support do you mean support for Compose Multiplatform or some UI framework independent solution (which will be much more complicated I think)? Also what platforms do you plan to support in addition to Android?
@colinrtwhite have you considered applying for a grant for this - http://kotlinfoundation.org/grants
@mxalbert1996 The goal is to support Kotlin Multiplatform and Compose Multiplatform with as many targets as possible. The Android target will have the most functionality by supporting lifecycles, views, and other Android concepts. Other targets will be focused on supporting fetching + decoding images with integration with coroutines and less platform-specific support.
I think we can accomplish this by replacing BitmapFactory
with skiko, which is the image decoder used by Compose Multiplatform, for non-Android targets. Migrating to Compose Multiplatform should be pretty straightforward once coil-base
has been converted to multiplatform. We'll just need to swap AndroidX Compose with Jetbrains Compose.
The biggest challenge I see at the moment is refactoring Context
references so ImageLoader
and other classes aren't coupled with Context
. Currently, we pass a Context
object deep into ImageLoader
's classes.
Good news! Any idea if skiko will be more or less performant than BitmapFactory on Android?
For the Context I tend to use a ContentProvider that hold a static reference to the application Context, so that it can be used in androidMain code without being declared in commonMain. Do you see any issue with this approach? Is there a limitation with theme / image loading requiring the Activity/fragment context instead?
@colinrtwhite Don't you think about making a development branch for working on this feature so we can contribute and make this process faster
@glureau My guess is it would be slightly slower given BitmapFactory
is an Android framework class, which is why we should continue to use BitmapFactory
on Android and skiko only on non-Android targets. For Context
I'd prefer to avoid content providers and have the user pass a Context
when building the ImageLoader
.
@MohamedRejeb Will do! I'm going to create a 3.x
branch that folks can contribute to once I've handled some of the initial multiplatform migration.
To use BitmapFactory
on Android is the right decision because Skiko is not a lightweight library 😉
@colinrtwhite Is there a plan to migrate from OkHttp to Ktor for sending HTTP requests to support for Kotlin Multiplatform Mobile?
Or are you planning to use different HTTP clients depending on the environment?
@sonatard That's still up for discussion. I think it's likely we migrate to Ktor and make it an optional dependency to support https://github.com/coil-kt/coil/issues/1648.
I'm relieved that Ktor has become the standard.
As many libraries are advancing their support for KMM using Ktor, it's pleasing to be able to reduce dependencies on other libraries like okHttp.
Most will driver ktor with okhttp
On Wed, 17 May 2023, 03:49 sonatard, @.***> wrote:
I'm relieved that Ktor has become the standard.
As many libraries are advancing their support for KMM using Ktor, it's pleasing to be able to reduce dependencies on other libraries like okHttp.
— Reply to this email directly, view it on GitHub https://github.com/coil-kt/coil/issues/842#issuecomment-1550570657, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALPBKTY3Y3RPIRNP6EDSODXGQVBZANCNFSM5BOPLKOA . You are receiving this because you commented.Message ID: @.***>
Hmm, is it? Stable?
On Sat, 20 May 2023, 16:41 Natan Lifshitz, @.***> wrote:
Why migrate to ktor if okhttp already supports Kotlin Multiplatform?
— Reply to this email directly, view it on GitHub https://github.com/coil-kt/coil/issues/842#issuecomment-1555926634, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALPBKRMNRD4AMGN5XRUFR3XHDJYPANCNFSM5BOPLKOA . You are receiving this because you commented.Message ID: @.***>
I'm relieved that Ktor has become the standard.
As many libraries are advancing their support for KMM using Ktor, it's pleasing to be able to reduce dependencies on other libraries like okHttp.
+1 for using ktor
Hi Please pace yourself
I've been lurking this thread, just wanted to say congratulations https://kotlinfoundation.org/news/grants-program-winners-23/
@FunkyMuse Thanks! Huge thanks to the Kotlin team for selecting Coil for the grant. Also thanks to @eygraber for recommending I submit a proposal.
Quick update on multiplatform support: I've been hacking on support in the 3.x
branch and it's going fairly well. Core components like DiskCache
and MemoryCache
have already been migrated, but there's still plenty of work to do to integrate Skiko and refactor out references to Android classes. It looks like by and large the API should remain similar to 2.x
.
If folks are interested in helping out, I'd hold off for the moment until I can get it into a compilable state, though feel free to drop suggestions in this thread. I'll post again when it's ready.
great work dude :) really looking forward to it.
https://bugs.chromium.org/p/skia/issues/detail?id=12251
This probably needs to be addressed / fixed to support SVG on Desktop properly.
It's worth mentioning that Compose has a built-in platform-agnosticImageBitmap
, which is used as a parameter for the standard Image
composable. Coil can make use of the open-source Compose code to see how this ImageBitmap is drawn. Compose API also exposes asImageBitmap
extension function to convert a Android Bitmap
to a Compose ImageBitmap
.
@colinrtwhite what's the status of the 3.x
branch? Is it compilable and/or usable? Have a couple of KMP side projects that are still in the POC stage that I'd like to use Coil with, and they don't need stability anytime soon (honestly don't even need it to really work as long as it compiles and doesn't crash).
@eygraber Hope to have it publishing snapshots soon-ish. The branch currently doesn't compile, but it's getting close. Tests are still mostly Android-only and will need to be updated. I'll start publishing snapshots as soon as it compiles + can load a basic network image. Will post here as soon as that's ready.
Hi folks, I just enabled snapshot publishing for Coil 3.0.0 to maven's snapshot repository:
allprojects {
repositories {
maven("https://oss.sonatype.org/content/repositories/snapshots")
}
}
dependencies {
implementation("io.coil-kt.coil3:coil:3.0.0-SNAPSHOT")
implementation("io.coil-kt.coil3:coil-network:3.0.0-SNAPSHOT")
}
Documentation is still a WIP at the moment so here are some quick notes:
3.0.0
release. It's likely that there will be binary incompatible changes between snapshots which will break your build.coil-network
. You'll need to manually add NetworkFetcher.Factory()
to your image loader to load network images. Additionally, you'll need to add a Ktor engine.coil-base
was renamed to coil-core
to align with the naming conventions used by Coroutines, Ktor, and AndroidX.coil
-> coil3
. This is to avoid binary compatibility issues and allow running Coil 2 and Coil 3 in the same application side-by-side.Dispatchers.Main
. This is included by default on every platform except JVM. You'll need to add your own dependency on kotlinx-coroutines-swing
(or javafx
if you use that).Cache-Control
headers aren't currently supported but will be eventually. There's also a new CacheStrategy
interface where you can implement your own caching logic.commonMain
. Please feel free to submit PRs to the 3.x
branch with bug fixes, documentation improvements, etc.!ImageLoader
with Compose Multiplatform.Will likely cut a proper alpha01
in a few weeks after the snapshots are smoke tested and documentation is added.
@colinrtwhite I wish to help with the WASM support. What are the pending tasks ? How can I help ?
Probably ktor for once
@shibasis0801 Yep we're waiting on updates from Ktor, kotlinx-immutable-collections, Poko, ~and possibly others~ to support wasm.
Fixing https://github.com/drewhamilton/Poko/issues/235 is up for grabs and would unblock Coil.
EDIT: I think it's just those three. okio-fakefilesystem
doesn't have WASM support, but it's only a dependency for Coil's tests.
Looks like
kotlinx.collections.immutable
for K/Wasm was implemented here
there still isn't a release of that PR
WIP wasmJs
support is here, but runs into a compiler issue:
> Task :coil:wasmJsBrowserTest FAILED
Module not found: Error: Can't resolve './skiko.mjs'
If anyone knows how to work-around this feel free to add to that branch.
EDIT: Artifacts are now published with wasmJs
support, though Coil's test suite fails to run for wasm.
Hello @colinrtwhite maybe I made a mistake adding the snapshot but after adding the dependencies and the line for maven, I have the good coil3 package displaying, but inside there is no compose folder. So I can't reach AsyncImage and others things as in the sample. Is it normal?
@inveders
I think I faced the same problem. I had to change the JetBrains Compose version to 1.6.0-alpha01
, and it worked. In fact, I faced another issue:
Could not find org.jetbrains.skiko:skiko:0.7.90
but this one, I fixed by strictly declaring skiko
version:
commonMainImplementation("org.jetbrains.skiko:skiko") {
version {
strictly("0.7.89.1")
}
}
@inveders You need to add a dependency on Coil's Compose artifact:
implementation("io.coil-kt.coil3:coil-compose:3.0.0-SNAPSHOT")
@colinrtwhite Is there a plan to support svg artifact for multiplatform (android/ios)? I'd like to test coil3 in my projects but loading svg images is very crucial for it
@rustamsmax No plans yet as I'm focused improving on Coil's core and Compose integration.
I think it's possible to make coil-svg
multiplatform using org.jetbrains.skia.svg.SVGDOM
on non-Android platforms. I'd be open to a PR that adds support for this!
coil-gif
and coil-video
are unlikely to be multiplatform as I don't think Skiko provides animated image support or video frame support.
@rustamsmax No plans yet as I'm focused improving on Coil's core and Compose integration.
I think it's possible to make
coil-svg
multiplatform usingorg.jetbrains.skia.svg.SVGDOM
on non-Android platforms. I'd be open to a PR that adds support for this!
coil-gif
andcoil-video
are unlikely to be multiplatform as I don't think Skiko provides animated image support or video frame support.
There is GIF support in this awsome lib so there seems to be a way
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 aComposable
, or just link it to the Application lifecycle.