Is there a concept akin to webview in compose desk...
# compose-desktop
a
Is there a concept akin to webview in compose desktop?
b
Surely AWT must have something to offer for this.
d
So far, I've only found JavaFX's webview (which sucked) and JCEF (which is like 200 MB). Or there's a paid option if you have a lot of money.
After mucking about with JavaFX, I settled with JCEF
s
@Stuie How are you using a WebView in your TornadoFX app?
g
Yep, you need two different implementations of some WebView composable. You can use expect/actual for this, define it as expect composable in your common code and implement actual on platform specific modules. So in case of android you should use AndroidView composaple https://developer.android.com/jetpack/compose/interop/interop-apis#views-in-compose and standard Android WebView https://developer.android.com/reference/android/webkit/WebView
👍 1
s
@spierce7 I just use a JavaFX WebView. @gildor Thanks! I haven't really used
expect/actual
for creating a Composable (or much of anything else) so I'll need to do a bit of digging. Is there a good sample repository you know of? The examples in the compose-jb repo seem to be very basic, but perhaps I missed something in there.
b
Expect actual is just like an interface which has different implementations per-platform
👍 1
s
Yeah, that's a really good explanation. I think I'm having issues with it because of the extra dimension compared to the apps I usually build. I've got the following modules:
common
desktop
android
common
contains
androidMain
commonMain
and
desktopMain
desktop
contains
commonMain
and
jvmMain
android
just contains what I'm used to in a single-module Android app (I'm an Android developer most of the time).
common.commonMain
seems like the obvious place to put my `expect`s. Then have an
actual
in
desktop.jvmMain
that uses JavaFX WebView And an
actual
in
android
that uses Android's WebView. I'm trying that out now, but I've messed things up somewhere, it seems.
desktop.jvmMain
actual
is complaining that there's no
expect
in
desktop.commonMain
, which seems to be too specific, since I want to implement the same in
android
. I'll keep playing around, but I'd appreciate any pointers if you've got them. Apologies for the wall of text.
s
common
 contains 
androidMain
 
commonMain
 and 
desktopMain
desktop
 contains 
commonMain
 and 
jvmMain
This sounds wrong. Android should contain commonMain, and androidMain. Desktop should contain commonMain, and desktopMain. If you wanted to get pretty advanced you could also add another layer of jvmMain to be shared between android and desktop.
b
actual implementations must be in the same module as expect declarations, so expects in common.commonMain and actuals in desktop.jvmMain are simply impossible
s
common.commonMain
 seems like the obvious place to put my `expect`s.
Yes - this is correct.
expect
/
actual
is a way to enforce a compile time contract between platforms.
expect
is in the common layer, and then when you compile it, the compiler enforces a single resolved
actual
of it when it combines all the dependent source sets together (at least that’s my mental model for it)
b
To recap, if you place your expects in common.commonMain, you must provide actuals in common.androidMain and common.jvmMain for android and desktop respectively
🙏 1
s
@Big Chungus That makes sense. Otherwise you could ship something with an
expects
and not know if there's an
actual
out there outside your boundary. @spierce7 For which module? The project is the result of going through the
New Project
wizard, and choosing Compose multiplatform.
s
Try and get it working based on what martynas said, and if for some reason you can’t, I can help you figure it out
🙏 1
s
Well, before I give up for the year, I can't use the
org.openjfx.javafxplugin
in
common/build.gradle.kts
because
com.android.library
is already applied, and the javafxplugin applies the
java
plugin.
The 'java' plugin has been applied, but it is not compatible with the Android plugins.
Not sure if I can specify plugins for particular flavors, or where I would stick the
javafx
and
android
blocks. Here's what my
common/build.gradle.kts
looks like
b
Yeah, you need one mpp module with only kotlim plugin and just shared code. Then create two more that both depend on it - one for android and one for desktop. After that your desktop and android modules are completely independent from each other and can specify their own plugins without clashes.
s
Does that mean that it's not possible to define your UI in
common
if you need use something like a WebView which has platform-specific implementations not covered by Compose?
common
/`SomeScreen.kt`
Copy code
@Composable
expect fun SomeScreen() {}
The
actuals
have to be in
common
, but
actual fun SomeScreen
in the
desktopMain
sourceSet requires JavaFX with its WebView, and
actual fun SomeScreen
in the
androidMain
sourceSet requires the Android WebView. If I move the
expect
out of
common
, then it has to be to either the
android
or
desktop
module, at which point I can just define a solid implementation with no `expect`/`actual` , and then I have to define it again for the other platform. I cannot refer to either implementation within the
common
module.
I think I've arrived at the conclusion that I just need to create my UI once per platform, which I was hoping to avoid. It seems like I could avoid it if compose had a WebView that I could drop in, but I understand why that's not the case right now. Thanks to you all for your help, I'm stepping away from the computer for the next few hours. Happy new year!
s
Ok - so you have multiple modules? Just to make sure we’re on the same page, expect/actuals have to be contained in a single module.
I think I’ve arrived at the conclusion that I just need to create my UI once per platform, which I was hoping to avoid.
Maybe I’m not following everything you’ve said well enough, but if this is still over the WebView thing, I think you’ve arrived at the wrong conclusion. It’s difficult to follow discussion, because it sounds like you have a module called
common
, which is difficult to follow when there are common source sets. Think of it this way: Create a new module. A compose library called
compose-webview
. It will support 2 platforms, jvm and android. Here is the folder heirarchy: •
./compose-webview
src
▪︎
commonMain
▪︎
jvmMain
▪︎
androidMain
Inside
commonMain
there will be:
Copy code
@Compose
expect fun WebView(url: String)
Inside
jvmMain
you will have the corresponding
Copy code
@Compose
actual fun WebView(url: String) {
  // delegate to JavaFX WebView. I don't know how to do that
}
Copy code
@Compose
actual fun WebView(url: String) {
  // delegate to Android WebView using the interop apis: <https://developer.android.com/jetpack/compose/interop/interop-apis>
}
s
Won't I need to apply the
com.android.library
and javafx plugin in this new module, and then arrive at the same problem as before?
The 'java' plugin has been applied, but it is not compatible with the Android plugins.
s
Have you tried enabling java for your jvm / desktop sourceset?
That might allow you to not apply the Java plugin
g
JavaFX will not work without java plugin I am honestly not even sure that JavaFX supported by Compose Desktop, only AWT and Swing
a
@gildor does JavaFX use chromium?
g
No, JavaFx uses its own WebView implementation based on WebKit
I believe java-cef is a way to use WebView based on chromium, it is also not require javafx
s
I read something about JCEF being 200MB. It would also mean another partial migration, since my existing desktop app is already using JavaFX. Seems simpler to just write the UI code once per platform for now.
g
It's correct, this is the whole browser bundled
374 Views