compose-multiplatform icon indicating copy to clipboard operation
compose-multiplatform copied to clipboard

Make ResourceReader a public API

Open lamba92 opened this issue 6 months ago • 2 comments

Describe proposed changes and the issue being fixed

(Optional) Fixes [link to the issue]

Testing

(Optional) Describe how you tested your changes (provide a snippet or/and steps)

  • [x] Add Test to desktopTest SourceSet (Optional) This should be tested by QA

Release Notes

Features - Resources

  • Added JvmResourceReader API and made LocalResourceReader public to allow providing a custom classloader for desktop target

lamba92 avatar Jun 13 '25 14:06 lamba92

When you open the ResourceReader API to public it means you finalize a format of the internal strings serialization format:

suspend fun readPart(path: String, offset: Long, size: Long): ByteArray

that is why I haven't been ready to do that. The format was invented on the go and I haven't think to stabilize it yet.

One of the problem with these offset and size: CMP-5039 Overriding string resources causes crashes or inelligible strings

terrakok avatar Jun 16 '25 10:06 terrakok

When you open the ResourceReader API to public it means you finalize a format of the internal strings serialization format:

suspend fun readPart(path: String, offset: Long, size: Long): ByteArray

that is why I haven't been ready to do that. The format was invented on the go and I haven't think to stabilize it yet.

One of the problem with these offset and size: CMP-5039 Overriding string resources causes crashes or inelligible strings

We could annotate ResourceReader as internal. Alternatively we could provide a Configuration in the local composition for resource loaders. I would be far more incline on exposing unstable APIs with an optin-in marker rather creating a contraption. I believe that documenting properly in code can be sufficient to let users understand.

lamba92 avatar Jun 16 '25 12:06 lamba92

@lamba92 you marked all the "shouldn't this be private" comments as resolved without addressing them nor replying. I cannot unresolve them myself, but they are not resolved at all.

rock3r avatar Jun 17 '25 10:06 rock3r

@lamba92 you marked all the "shouldn't this be private" comments as resolved without addressing them nor replying. I cannot unresolve them myself, but they are not resolved at all.

Sorry, I forgot to send the comment. The whole point of this MR is to expose ResourceReader interface and its implementations to users so that it could be replaced. JvmResourceReader should be public because a user should be able to:

@Composable
fun WithCustomResourceReader(reader: ResourceLoader, content: @Composable () -> Unit) {
  CompositionLocalProvider(LocalResourceReader provides loader, content)
}

...
val reader = JvmResourceReader(this::class.java.classloader)
setContent {
  WithCustomResourceReader(reader) {
    ...
  }
}

Given that the JVM implementation is public, I do not see why the default ones for the other platforms should not be as well.

lamba92 avatar Jun 17 '25 14:06 lamba92

I can see why you'd want the JVM one to be public, but making others public is a bad idea for two reasons:

  1. You're adding public APIs you do not need and won't be able to easily change in the future (in a library you should keep a tight control of what API you publish, not just dump everything into the public API)
  2. Most (all?) other implementations are objects that can't be either extended nor instantiated, and it is thus pointless to expose them to begin with

rock3r avatar Jun 17 '25 14:06 rock3r

I added @ExperimentalResourceApi to the APIs I made public in this PR

lamba92 avatar Jun 18 '25 14:06 lamba92

❤️

lamba92 avatar Jul 03 '25 10:07 lamba92