Skip to content

Commit b26c25e

Browse files
authored
Merge pull request #7 from Sterta/main
Added support for evaluate javascript callback
2 parents d124d5c + 021c59e commit b26c25e

9 files changed

Lines changed: 74 additions & 33 deletions

File tree

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ state.cookieManager.removeAllCookies()
145145
navigator.evaluateJavaScript("document.title = 'Hello'")
146146
```
147147

148-
Desktop is currently **fire-and-forget**.
149-
150148
---
151149

152150
### JS ↔ Kotlin bridge 🌉

demo-shared/src/commonMain/kotlin/io/github/kdroidfilter/webview/demo/App.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,10 @@ fun App() {
291291
jsSnippet = jsSnippet,
292292
onJsSnippetChange = { jsSnippet = it },
293293
onRunJs = {
294-
navigator.evaluateJavaScript(jsSnippet)
295294
log("evaluateJavaScript bytes=${jsSnippet.length}")
295+
navigator.evaluateJavaScript(jsSnippet) {
296+
log("evaluateJavaScript result=$it")
297+
}
296298
},
297299
onCallNativeFromJs = {
298300
val script =
@@ -399,8 +401,10 @@ fun App() {
399401
jsSnippet = jsSnippet,
400402
onJsSnippetChange = { jsSnippet = it },
401403
onRunJs = {
402-
navigator.evaluateJavaScript(jsSnippet)
403404
log("evaluateJavaScript bytes=${jsSnippet.length}")
405+
navigator.evaluateJavaScript(jsSnippet) {
406+
log("evaluateJavaScript result=$it")
407+
}
404408
},
405409
onCallNativeFromJs = {
406410
val script =

webview-compose/src/androidMain/kotlin/io/github/kdroidfilter/webview/web/AndroidWebView.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,12 @@ internal class AndroidWebView(
7474

7575
override fun stopLoading() = webView.stopLoading()
7676

77-
override fun evaluateJavaScript(script: String) {
78-
webView.evaluateJavascript(script, null)
77+
override fun evaluateJavaScript(script: String, callback: ((String) -> Unit)?) {
78+
val androidScript = "javascript:$script"
79+
KLogger.d {
80+
"evaluateJavaScript: $androidScript"
81+
}
82+
webView.evaluateJavascript(androidScript, callback)
7983
}
8084

8185
override fun injectJsBridge() {

webview-compose/src/commonMain/kotlin/io/github/kdroidfilter/webview/web/IWebView.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ interface IWebView {
4747

4848
fun evaluateJavaScript(
4949
script: String,
50+
callback: ((String) -> Unit)? = null
5051
)
5152

5253
suspend fun loadContent(content: WebContent) {

webview-compose/src/commonMain/kotlin/io/github/kdroidfilter/webview/web/WebViewNavigator.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class WebViewNavigator(
4545

4646
data class EvaluateJavaScript(
4747
val script: String,
48+
val callback: ((String) -> Unit)? = null
4849
) : NavigationEvent
4950
}
5051

@@ -91,7 +92,7 @@ class WebViewNavigator(
9192
)
9293

9394
is NavigationEvent.LoadHtmlFile -> loadHtmlFile(event.fileName, event.readType)
94-
is NavigationEvent.EvaluateJavaScript -> evaluateJavaScript(event.script)
95+
is NavigationEvent.EvaluateJavaScript -> evaluateJavaScript(event.script, event.callback)
9596
}
9697
}
9798
}
@@ -134,8 +135,9 @@ class WebViewNavigator(
134135

135136
fun evaluateJavaScript(
136137
script: String,
138+
callback: ((String) -> Unit)? = null
137139
) {
138-
coroutineScope.launch { navigationEvents.emit(NavigationEvent.EvaluateJavaScript(script)) }
140+
coroutineScope.launch { navigationEvents.emit(NavigationEvent.EvaluateJavaScript(script, callback)) }
139141
}
140142

141143
fun navigateBack() {

webview-compose/src/iosMain/kotlin/io/github/kdroidfilter/webview/web/IOSWebView.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,16 @@ internal class IOSWebView(
188188
}
189189

190190
@OptIn(ExperimentalForeignApi::class)
191-
override fun evaluateJavaScript(script: String) {
192-
webView.evaluateJavaScript(script, completionHandler = null)
191+
override fun evaluateJavaScript(script: String, callback: ((String) -> Unit)?) {
192+
webView.evaluateJavaScript(script) { result, error ->
193+
if (callback == null) return@evaluateJavaScript
194+
if (error != null) {
195+
KLogger.e { "evaluateJavaScript error: $error" }
196+
callback.invoke(error.localizedDescription())
197+
} else {
198+
callback.invoke(result?.toString() ?: "")
199+
}
200+
}
193201
}
194202

195203
override fun injectJsBridge() {

webview-compose/src/jvmMain/kotlin/io/github/kdroidfilter/webview/web/DesktopWebView.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,13 @@ internal class DesktopWebView(
9999

100100
override fun stopLoading() = webView.stopLoading()
101101

102-
override fun evaluateJavaScript(
103-
script: String,
104-
) {
105-
webView.evaluateJavaScript(script)
102+
override fun evaluateJavaScript(script: String, callback: ((String) -> Unit)?) {
103+
KLogger.d {
104+
"evaluateJavaScript: $script"
105+
}
106+
webView.evaluateJavaScript(script) { result ->
107+
callback?.invoke(result)
108+
}
106109
}
107110

108111
override fun injectJsBridge() {

wrywebview/src/main/kotlin/io/github/kdroidfilter/webview/wry/WryWebViewPanel.kt

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,22 @@ class WryWebViewPanel(
162162
log("stopLoading webviewId=$webviewId")
163163
}
164164

165-
fun evaluateJavaScript(script: String) {
166-
val action = { webviewId?.let { NativeBindings.evaluateJavaScript(it, script) } }
167-
if (SwingUtilities.isEventDispatchThread()) {
168-
action()
169-
} else {
170-
SwingUtilities.invokeLater { action() }
165+
fun evaluateJavaScript(script: String, callback: (String) -> Unit) {
166+
val id = webviewId ?: run {
167+
callback("")
168+
return
169+
}
170+
log("evaluateJavaScript bytes=${script.length} webviewId=$id")
171+
try {
172+
NativeBindings.evaluateJavaScript(id, script, object : JavaScriptCallback {
173+
override fun onResult(result: String) {
174+
callback(result)
175+
}
176+
})
177+
} catch (e: Exception) {
178+
log("evaluateJavaScript failed: ${e.message}")
179+
callback("")
171180
}
172-
log("evaluateJavaScript bytes=${script.length} webviewId=$webviewId")
173181
}
174182

175183
fun getCurrentUrl(): String? {
@@ -690,8 +698,8 @@ private object NativeBindings {
690698
io.github.kdroidfilter.webview.wry.stopLoading(id)
691699
}
692700

693-
fun evaluateJavaScript(id: ULong, script: String) {
694-
io.github.kdroidfilter.webview.wry.evaluateJavascript(id, script)
701+
fun evaluateJavaScript(id: ULong, script: String, callback: JavaScriptCallback) {
702+
io.github.kdroidfilter.webview.wry.evaluateJavascript(id, script, callback)
695703
}
696704

697705
fun getUrl(id: ULong): String {

wrywebview/src/main/rust/lib.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -478,24 +478,37 @@ pub fn stop_loading(id: u64) -> Result<(), WebViewError> {
478478
run_on_main_thread(move || stop_loading_inner(id))
479479
}
480480

481-
fn evaluate_javascript_inner(id: u64, script: String) -> Result<(), WebViewError> {
482-
eprintln!(
483-
"[wrywebview] evaluate_javascript id={} bytes={}",
484-
id,
485-
script.len()
486-
);
487-
with_webview(id, |webview| webview.evaluate_script(&script).map_err(WebViewError::from))
481+
#[uniffi::export(callback_interface)]
482+
pub trait JavaScriptCallback: Send + Sync {
483+
fn on_result(&self, result: String);
484+
}
485+
486+
fn evaluate_javascript_inner(
487+
id: u64,
488+
script: String,
489+
callback: Box<dyn JavaScriptCallback>,
490+
) -> Result<(), WebViewError> {
491+
with_webview(id, |webview| {
492+
let _ = webview.evaluate_script_with_callback(&script, move |result| {
493+
callback.on_result(result);
494+
});
495+
Ok(())
496+
})
488497
}
489498

490499
#[uniffi::export]
491-
pub fn evaluate_javascript(id: u64, script: String) -> Result<(), WebViewError> {
500+
pub fn evaluate_javascript(
501+
id: u64,
502+
script: String,
503+
callback: Box<dyn JavaScriptCallback>,
504+
) -> Result<(), WebViewError> {
492505
#[cfg(target_os = "linux")]
493506
{
494-
return run_on_gtk_thread(move || evaluate_javascript_inner(id, script));
507+
return run_on_gtk_thread(move || evaluate_javascript_inner(id, script, callback));
495508
}
496509

497510
#[cfg(not(target_os = "linux"))]
498-
run_on_main_thread(move || evaluate_javascript_inner(id, script))
511+
run_on_main_thread(move || evaluate_javascript_inner(id, script, callback))
499512
}
500513

501514
fn go_back_inner(id: u64) -> Result<(), WebViewError> {

0 commit comments

Comments
 (0)