JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.87k stars 1.15k forks source link

Catch-22 calling singleWindowApplication with icon parameter #2369

Open hakanai opened 1 year ago

hakanai commented 1 year ago

In my main function, I tried to add an icon:

fun main() = singleWindowApplication(
    title = "Calculator",
    icon = painterResource("/AppIcon.png"),
) {
    MainUi()
}

This fails to compile:

e: ...\Main.kt: (7, 5): Functions which invoke @Composable functions must be marked with the @Composable annotation
e: ...\Main.kt: (9, 12): @Composable invocations can only happen from the context of a @Composable function

Fair enough, so I try to make the function @Composable:

@Composable
fun main() = singleWindowApplication(
    title = "Calculator",
    icon = painterResource("/AppIcon.png"),
) {
    MainUi()
}

This fails to compile too:

e: ...\Main.kt: (9, 5): Composable main functions are not currently supported

So it seems impossible to call painterResource in order to pass the painter in as the icon. Maybe there is an alternative way to get an icon, but I wasn't able to find it and the docs don't even talk about how to get an icon. The painterResource function itself is implemented using internal functions, so there doesn't seem to be anything lower level I can use that isn't composable?

As a workaround, avoiding using singleWindowApplication works fine:

fun main() = application {
    Window(
        ::exitApplication,
        title = "Calculator",
        icon = painterResource("/AppIcon.png"),
    ) {
        MainUi()
    }
}

But if the icon parameter is going to remain on singleWindowApplication, it would be nice if it were possible to use that.

igordmn commented 1 year ago

Thanks, this API issue is known, and people often stumble on it.

The current way to set icon in singleWindowApplication exists (described in docs), but it is verbose:

icon = BitmapPainter(useResource("sample.png", ::loadImageBitmap))

We shouldn't remove icon parameter from singleWindowApplication or singleWindowApplication itself. Instead, we should simplify API for loading resources outside of Composable world.

Also, one of the options is to change icon: Painter to icon: @Composable () -> Painter

okushnikov commented 1 month ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.