Kamel-Media / Kamel

Kotlin asynchronous media loading and caching library for Compose.
Apache License 2.0
595 stars 23 forks source link

Updating to compose 1.2.0-alpha build issue #20

Closed luca992 closed 1 year ago

luca992 commented 2 years ago

This is not an issue with the current release. But I am attempting to update the project to use the latest compose-jb alpha 1.2.0-alpha01-dev707 supporting kotlin 1.6.21 to add js and native targets.

When building I get the error:

LazyPainterResource.kt: (49, 17): @Composable invocations can only happen from the context of a @Composable function

which is caused by: rememberVectorPainter being called in the map callback where map is not a @Composable function. And also it is called inside a flow. Which isn't allowed in the latest compose version. So this would probably need a rework.

        "xml" -> kamelConfig.loadImageVectorResource(data, resourceConfig).map { resource ->
            resource.map { imageVector ->
                rememberVectorPainter(imageVector)
            }
        }

I'm trying to think of a way to handle this. Would completely removing use of flows by loadImageVectorResource be an acceptable solution for vectors, as rememberVectorPainter can't be called inside a flow?

which would look something like this:

        "xml" -> flowOf(kamelConfig.loadImageVectorResource(coroutineScope, data, resourceConfig)
            .map { imageVector ->
                rememberVectorPainter(imageVector)
            }
        )

Or does anyone have another suggestion?

alialbaali commented 1 year ago

I have currently updated the compose version to the latest alpha, and I'm facing this problem. It worked before, I don't understand what's the problem now. Do you have any idea?

luca992 commented 1 year ago

@alialbaali Well I explained the issue above. I was planning to take a look at it again soon. Rn I can't remember the exact details of the issue. But I was wondering:

I'm trying to think of a way to handle this. Would completely removing use of flows by loadImageVectorResource be an acceptable solution for vectors, as rememberVectorPainter can't be called inside a flow?

To me seems that your solution to cache vector resources might not been needed as rememberVectorPainter can accomplish that? Or am I misunderstanding something

alialbaali commented 1 year ago

How about this?

    val painterResource by remember(data, resourceConfig) {
        when (data.toString().substringAfterLast(".")) {
            "svg" -> kamelConfig.loadSvgResource(data, resourceConfig)
            "xml" -> kamelConfig.loadImageVectorResource(data, resourceConfig)
            else -> kamelConfig.loadImageBitmapResource(data, resourceConfig)
        }
    }.collectAsState(Resource.Loading(0F), resourceConfig.coroutineContext)

    return painterResource.map { value ->
        when (value) {
            is ImageVector -> rememberVectorPainter(value)
            is ImageBitmap -> remember(value) { BitmapPainter(value, filterQuality = filterQuality) }
            else -> remember(value) { value as Painter }
        }
    }
alialbaali commented 1 year ago

This should be fixed in version 0.4.0.

luca992 commented 1 year ago

working for me now 👍 thanks