KevinnZou / compose-webview-multiplatform

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

Finding way to Communicate with Java script function #31

Closed jk2pr closed 5 months ago

jk2pr commented 7 months ago

My requirement is to communicate with a JavaScript function from native code, similar to what we usually do in the old way by adding ‘addJavascriptInterface’ in WebView. I am exploring this library, but I can’t find any way to communicate with JavaScript code through it.

realityexpander commented 7 months ago

I just asked this same question in the discussion area! lol

KevinnZou commented 7 months ago

Thank you for the suggestion! After conducting some research, I think it is feasible to support that feature. I will incorporate it into my plan and work on implementing it as soon as I can. You are also welcome to submit PR if you are willing to. Thanks again!

DatL4g commented 7 months ago

I think we have to push this issue a bit back as this is much more work than you might thought @KevinnZou

This will require code generation, which means a compiler plugin with KSP. The generated code must be safe JavaScript since we inject it as such.

I mean we could add the Android method without much work I guess, but Multiplatform Support is another level.

KevinnZou commented 7 months ago

I think we have to push this issue a bit back as this is much more work than you might thought @KevinnZou

This will require code generation, which means a compiler plugin with KSP. The generated code must be safe JavaScript since we inject it as such.

I mean we could add the Android method without much work I guess, but Multiplatform Support is another level.

Yes, after deep research, I also realized that it is far more complicated than I thought before. We must develop a functionality similar to JSBridge, which requires us to design a communication channel between Native and H5. However, I will work with @DatL4g to find a solution after we address the existing issues. It may take some time and thank you in advance for your patience. I will keep updating our latest progress here.

IlyaPavlovskii commented 6 months ago

Maybe anybody found any lifehack solutions? Maybe it's possible with evaluateJavaScript ?

KevinnZou commented 6 months ago

Maybe anybody found any lifehack solutions? Maybe it's possible with evaluateJavaScript ?

Apologies for the lack of support for this functionality at the moment. As mentioned earlier, this issue is complex and cannot be easily resolved using evaluateJavaScript. I have begun working on it but I am facing issues with the iOS side. I will continue to work on resolving these problems, but please note that it may take some time as I can only dedicate my time to this project after work.

IlyaPavlovskii commented 6 months ago

As temp solution, I've started to change the document title(simulation JS bridge communication) and listen it:

function sendStateChange(newState) {
    document.title = 'ytplayer://onStateChange?data='+newState;
}
val action = YouTubeActionHandler.handleAction(webViewState.pageTitle)

object YouTubeActionHandler {

    private const val SCHEME = "ytplayer"
    private const val DATA_KEY = "data"

    fun handleAction(url: String?): YouTubeEvent? {
        val uri = url?.let { Uri.fromStringOrNull(uriString = it) } ?: return null
        return if (uri.scheme == SCHEME) {
            val operation = uri.host?.let(YouTubeOperation.Companion::fromStringOrNull)
            val data = uri.queryParameters()[DATA_KEY].orEmpty()
            println("webViewState. OPERATION_HANDLED: Path: ${uri.path} " +
                    "Operation: $operation " +
                    "Params: ${uri.queryParameters()} " +
                    "Data: ${uri.queryParameters()[DATA_KEY]}")
            YouTubeEvent.fromStringOrNull(operation, data)
        } else {
            null
        }
    }
}

more info in my repo: https://github.com/IlyaPavlovskii/YouTubePlayer/blob/main/player.html#L115 https://github.com/IlyaPavlovskii/YouTubePlayer/blob/main/features/youtubeplayer/src/commonMain/kotlin/io/github/ilyapavlovskii/multiplatform/youtubeplayer/YouTubePlayer.kt#L119

Shabinder commented 6 months ago

https://github.com/cashapp/zipline

@KevinnZou @DatL4g Refer above, shall help in generating a safe and better designed way to communicate across host and javascript worlds, and also will have most of the work done, regarding code generation and so...

Shabinder commented 6 months ago

but since above uses quickJS Lib, that might not be the desired endgoal, since mostly users would like to do this in webview itself. So that might need to be changed.

KevinnZou commented 6 months ago

https://github.com/cashapp/zipline

@KevinnZou @DatL4g Refer above, shall help in generating a safe and better designed way to communicate across host and javascript worlds, and also will have most of the work done, regarding code generation and so...

Thank you for your suggestion! I will look into it and see how we can incorporate it into our project.

KevinnZou commented 5 months ago

Hello everyone, I just wanted to provide a brief update.

I have completed the development of the basic architecture and performed initial testing. It currently supports native-side registration of JS processors to receive JS calls and return results.

You can test this feature using the provided example in this branch. Please note that the code may be messy as I just finished the development. I apologize for any inconvenience.

I would appreciate it if you could test it and provide feedback. If all goes well, I will release a snapshot version for testing next week and publish the official version by the end of the month.

Thanks!

KevinnZou commented 5 months ago

Hi guys, I have released version 1.8.0-SNAPSHOT for testing this new feature. To import it, you have to add this repo: maven("https://s01.oss.sonatype.org/content/repositories/snapshots")

For instructions on how to use it, please refer to this link.

Please let me know if you encounter any problems or if you would like any new features. Thanks!

tomastiminskas commented 5 months ago

@KevinnZou Thanks for having this feature out so quickly. I was reading the instructions and it sounds there's a way to communicate back and forth with the web view now. I will do some tests using this version tomorrow or the day after and will let you know if I run into any issues

nickfaces commented 5 months ago

@KevinnZou I am observing strange behavior. Initially, I open a webview, when I click on certain places inside webview, I receive a message , and in this case jbridge works correctly. However, if I go to another web page by changing the url, or using navigator.loadUrl(), and even if I just use navigator.reload(), then JsMessageHandler is no longer working and I do not receive any messages from webview.

KevinnZou commented 5 months ago

@nickfaces This is likely because the injected JS code is cleared when a new page is loaded. To address this issue, I have modified the code to inject the JS code every time a page is loaded. The updated code has been pushed to Maven. Please give it a try and let me know if you have any additional questions. Thank you!

nickfaces commented 5 months ago

@KevinnZou Works great now when changing the URL, but does not work when going back via backpress (unless of course it should work in this case)

KevinnZou commented 5 months ago

@KevinnZou Works great now when changing the URL, but does not work when going back via backpress (unless of course it should work in this case)

@nickfaces Thanks for your feedback! Yes, it turns out that using webview.goback does not cause the loading state to change. I will try to find a way to make it work.

KevinnZou commented 5 months ago

@KevinnZou Works great now when changing the URL, but does not work when going back via backpress (unless of course it should work in this case)

@nickfaces I solved the issue by injecting the JS code whenever the URL changes. Please try it out and let me know if you encounter any new problems. Thank you!

KevinnZou commented 5 months ago

Hi guys, I have released version 1.8.0-SNAPSHOT for testing this new feature. To import it, you have to add this repo: maven("https://s01.oss.sonatype.org/content/repositories/snapshots")

For instructions on how to use it, please refer to this link.

Please let me know if you encounter any problems or if you would like any new features. Thanks!

Hello everyone, I have released version 1.8.0-SNAPSHOT of JSBridge to MavenCentral, including all functionalities. I invite you to test it and share your suggestions. If all goes smoothly, I plan to publish version 1.8.0 next week.

tomastiminskas commented 5 months ago

@KevinnZou it might be something on our website but I tested with different websites and when running webViewNavigator.evaluateJavaScript to send a message, the msg is never received on the website and I'm seeing this error on the Android Studio console:

INFO:CONSOLE(24)] "Uncaught Error: Invalid arguments; expecting a single integer", source: https://test-auth-flow.vercel.app/ (24)

Any ideas?

KevinnZou commented 5 months ago

@KevinnZou it might be something on our website but I tested with different websites and when running webViewNavigator.evaluateJavaScript to send a message, the msg is never received on the website and I'm seeing this error on the Android Studio console:

INFO:CONSOLE(24)] "Uncaught Error: Invalid arguments; expecting a single integer", source: https://test-auth-flow.vercel.app/ (24)

Any ideas?

@tomastiminskas Thanks for your feedback! Could you provide the platform that you are running on? Also, did you try to run some simple scripts like console.log?

KevinnZou commented 5 months ago

Hello everyone, JsBridge has been released in version 1.8.0. Please have a try and let me know if you encounter any problems.