KevinnZou / compose-webview-multiplatform

WebView for JetBrains Compose Multiplatform
https://kevinnzou.github.io/compose-webview-multiplatform/
Apache License 2.0
530 stars 69 forks source link

Use in the Desktop rememberWebViewStateWithHTMLData not loaded correctly #61

Closed pdcodkzcap04 closed 10 months ago

pdcodkzcap04 commented 11 months ago

Hello, I have integrated your component into my sample application, but now I'm encountering an issue. When I use 'rememberWebViewStateWithHTMLData' to load data in Desktop, it prompts me with the following error message: image

Additionally, the content is blank, without any data.

image

I'm running on Mac and have added the following.

Screen

    val html = """
            <html>
                <head>
                    <title>Custom Title</title>
                </head>
                <body>
                    <h1>Custom HTML</h1>
                    <p>This is a custom HTML page.</p>
                </body>
            </html>
    """.trimIndent()
    val webViewState = rememberWebViewStateWithHTMLData(
        html
    )
    Column(
        modifier = Modifier.fillMaxSize()
    ) {
        LedgerTitle(title = state.title, onBack = {
            onEvent(AgreementEvent.GoBack)
        })
        WebView(
            modifier = Modifier.fillMaxSize(),
            state = webViewState
        )
    }

Gradle

afterEvaluate {
    tasks.withType<JavaExec> {
        jvmArgs("--add-opens", "java.desktop/sun.awt=ALL-UNNAMED")
        jvmArgs("--add-opens", "java.desktop/java.awt.peer=ALL-UNNAMED")

        if (System.getProperty("os.name").contains("Mac")) {
            jvmArgs("--add-opens", "java.desktop/sun.awt=ALL-UNNAMED")
            jvmArgs("--add-opens", "java.desktop/sun.lwawt=ALL-UNNAMED")
            jvmArgs("--add-opens", "java.desktop/sun.lwawt.macosx=ALL-UNNAMED")
        }
    }
}
pdcodkzcap04 commented 11 months ago

However, when I load a hyperlink, the content is displayed correctly.

image

KevinnZou commented 11 months ago

@pdcodkzcap04 Hi, Thank you for your feedback! Which version of this library are you using? Additionally, are you using a Mac M1 or an Intel?

pdcodkzcap04 commented 11 months ago

@pdcodkzcap04您好,感谢您的反馈!您使用的是该库的哪个版本?另外,您使用的是 Mac M1 还是 Intel?

Hello, the version of the library I'm using is 1.7.6, and the chip in my computer is Apple M1 Pro.

KevinnZou commented 11 months ago

@pdcodkzcap04 Thanks for your information! Did you follow this instruction and set up the KCEF browser correctly? I just tested your code on my Mac Intel and it works well.

pdcodkzcap04 commented 11 months ago

@KevinnZou Yes, I have compared the documentation multiple times for validation, but I am still unable to load it correctly.

@OptIn(ExperimentalDecomposeApi::class)
fun main() = application {
   // ...
    Window(
        title = "Custom App",
        onCloseRequest = ::exitApplication,
        state = windowState
    ) {
        LaunchedEffect(Unit) {
            withContext(Dispatchers.IO) {
                KCEF.init(builder = {
                    installDir(File("kcef-bundle"))
                    progress {
                        onDownloading {
                            println("Downloading: $it")
                        }
                        onInitialized {
                            println("Initialized")
                        }
                    }
                    settings {
                        cachePath = File("cache").absolutePath
                    }
                }, onError = {
                    println(it)
                })
            }
        }
        PredictiveBackGestureOverlay(
            backDispatcher = backDispatcher, // Use the same BackDispatcher as above
            backIcon = null,
            modifier = Modifier.fillMaxSize(),
        ) {
            App(root)
        }

        DisposableEffect(Unit){
            onDispose {
                KCEF.disposeBlocking()
            }
        }
    }
}
compose.desktop {
    application {
       // ...
        buildTypes.release.proguard {
            configurationFiles.from("compose-desktop.pro")
        }
    }
}
KevinnZou commented 11 months ago

@DatL4g Could you have a look at this issue? I think he is doing everything correctly. Is that because KCEF does not work with Mac M1?

pdcodkzcap04 commented 11 months ago

@KevinnZou I have identified the issue, but I am not sure of the reason. I will inform you of the specific steps later.

pdcodkzcap04 commented 11 months ago

@KevinnZou @DatL4g In the sample application, the 'WebViewApp' uses 'WebViewSample()' to load content. The code is as follows:

@OptIn(ExperimentalResourceApi::class)
@Composable
internal fun WebViewSample() {
    MaterialTheme {
        val html = """
        <html>
            <head>
                <title>Custom Title</title>
            </head>
            <body>
                <h1>Hello, World!</h1>
            </body>
        </html>
    """.trimIndent()
        val webViewState = rememberWebViewStateWithHTMLData(
            data = html
        )
        webViewState.webSettings.apply {
            isJavaScriptEnabled = true
            customUserAgentString =
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/625.20 (KHTML, like Gecko) Version/14.3.43 Safari/625.20"
            androidWebSettings.apply {
                isAlgorithmicDarkeningAllowed = true
                safeBrowsingEnabled = true
            }
        }
        Column(Modifier.fillMaxSize()) {
            val text =
                webViewState.let {
                    "${it.pageTitle ?: ""} ${it.loadingState} ${it.lastLoadedUrl ?: ""}"
                }
            Row {
                // The location of the error
                Icon(
                    painter = painterResource("ic_back.xml"),
                    contentDescription = "multiplatform",
                    modifier = Modifier
                        .size(100.dp)
                )
                Text(text)
            }
            WebView(
                state = webViewState,
                modifier = Modifier.fillMaxSize(),
            )
        }
    }
}

image

ic_back.xml

<vector android:height="50dp" android:viewportHeight="1024"
    android:viewportWidth="1024" android:width="50dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#000000" android:pathData="M395.2,513.6l323.1,-312.4c19.1,-18.4 19.1,-48.3 0,-66.7 -19.1,-18.4 -49.9,-18.4 -69,0L291.8,480.3c-19.1,18.4 -19.1,48.3 0,66.7l357.6,345.7c9.5,9.2 22,13.8 34.5,13.8 12.5,0 25,-4.6 34.5,-13.8 19.1,-18.4 19.1,-48.2 0,-66.7L395.2,513.6z"/>
</vector>

In the sample application, when I add an "Icon" to the "WebView" and load resources from the "resources" folder, an error occurs. The "Icon" loads correctly, but the "WebView" fails to load.

pdcodkzcap04 commented 11 months ago

If I use Icons from the Material library, the same error occurs.

        Column(Modifier.fillMaxSize()) {
            val text =
                webViewState.let {
                    "${it.pageTitle ?: ""} ${it.loadingState} ${it.lastLoadedUrl ?: ""}"
                }
            Row {
                // The location of the error
                Icon(
                    imageVector = Icons.Default.ArrowBack,
                    contentDescription = "multiplatform",
                    modifier = Modifier
                        .size(100.dp)
                )
                Text(text)
            }
            WebView(
                state = webViewState,
                modifier = Modifier.fillMaxSize(),
            )
        }

After removing the 'Icon', my 'WebView' loads correctly.

image

DatL4g commented 11 months ago

My first guess here would be that the loading process probably happens on the main thread and gets blocked by loading other resources on the same thread in this time. Would explain #58 as well (blocking the main thread).

@pdcodkzcap04 You could try setting up the browser yourself like this: https://github.com/DatL4g/Burning-Series/blob/compose/app/shared/src/desktopMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/activate/component/WebView.desktop.kt You can ignore the LaunchedEffect inside and you can use client.createBrowserWithHtml for the browser instance instead

KevinnZou commented 11 months ago
        Column(Modifier.fillMaxSize()) {
            val text =
                webViewState.let {
                    "${it.pageTitle ?: ""} ${it.loadingState} ${it.lastLoadedUrl ?: ""}"
                }
            Row {
                // The location of the error
                Icon(
                    imageVector = Icons.Default.ArrowBack,
                    contentDescription = "multiplatform",
                    modifier = Modifier
                        .size(100.dp)
                )
                Text(text)
            }
            WebView(
                state = webViewState,
                modifier = Modifier.fillMaxSize(),
            )
        }

I also reproduced the issue with the above code. It does not even start to load the web. 20231211-201136

@DatL4g Is there a way to solve it without interacting with the CEF browser? It can be complicated for developers to figure out how to use it.

pdcodkzcap04 commented 11 months ago

Hello, my friend, has a solution been found for this issue?

Chen-Xi-g commented 11 months ago

I had the same problem

KevinnZou commented 11 months ago

@DatL4g Has there been any progress on this issue? It is currently blocking the main process, so please prioritize it.

Chen-Xi-g commented 10 months ago

Has this issue been resolved?

KevinnZou commented 10 months ago

@Chen-Xi-g @pdcodkzcap04 I have identified the problem and am currently working on a solution. It will be fixed in version 1.8.4, which is scheduled for release next week. Apologies for any inconvenience caused by this issue.