@@ -6,11 +6,13 @@ import androidx.compose.runtime.getValue
6
6
import androidx.compose.runtime.rememberUpdatedState
7
7
import androidx.compose.ui.Modifier
8
8
import androidx.compose.ui.awt.SwingPanel
9
- import javafx.embed.swing.JFXPanel
10
9
import javafx.application.Platform
10
+ import javafx.concurrent.Worker
11
+ import javafx.embed.swing.JFXPanel
11
12
import javafx.scene.Scene
12
13
import javafx.scene.layout.StackPane
13
14
import javafx.scene.web.WebView
15
+ import java.net.URL
14
16
15
17
@Composable
16
18
actual fun OoniWebView (
@@ -21,31 +23,93 @@ actual fun OoniWebView(
21
23
val onCreated = {}
22
24
val onDispose = {}
23
25
val currentOnDispose by rememberUpdatedState(onDispose)
24
-
25
- DisposableEffect (Unit ) {
26
- onDispose {
27
- currentOnDispose()
28
- }
29
- }
26
+ val event = controller.rememberNextEvent()
30
27
31
28
SwingPanel (
32
29
factory = {
33
30
JFXPanel ().apply {
34
31
Platform .runLater {
35
32
val webView = WebView ().apply {
36
33
isVisible = true
37
- // engine.addLoadListener(state, navigator)
38
34
engine.isJavaScriptEnabled = true
35
+
36
+ // Set up load listeners
37
+ engine.loadWorker.stateProperty().addListener { _, _, newValue ->
38
+ when (newValue) {
39
+ Worker .State .SCHEDULED -> {
40
+ controller.state = OoniWebViewController .State .Loading (0f )
41
+ }
42
+ Worker .State .RUNNING -> {
43
+ val progress = engine.loadWorker.progress
44
+ controller.state = OoniWebViewController .State .Loading (progress.toFloat())
45
+ }
46
+ Worker .State .SUCCEEDED -> {
47
+ controller.state = OoniWebViewController .State .Successful
48
+ controller.canGoBack = engine.history.currentIndex > 0
49
+ }
50
+ Worker .State .FAILED -> {
51
+ controller.state = OoniWebViewController .State .Failure
52
+ controller.canGoBack = engine.history.currentIndex > 0
53
+ }
54
+ else -> {}
55
+ }
56
+ }
57
+
58
+ // Domain restriction
59
+ engine.locationProperty().addListener { _, _, newLocation ->
60
+ try {
61
+ val host = URL (newLocation).host
62
+ val allowed = allowedDomains.any { domain ->
63
+ host.matches(Regex (" ^(.*\\ .)?$domain $" ))
64
+ }
65
+
66
+ if (! allowed) {
67
+ engine.load(" about:blank" )
68
+ }
69
+ } catch (e: Exception ) {
70
+ // Invalid URL, ignore
71
+ }
72
+ controller.canGoBack = engine.history.currentIndex > 0
73
+ }
39
74
}
75
+
40
76
val root = StackPane ()
41
77
root.children.add(webView)
42
78
this .scene = Scene (root)
43
- // state.webView = DesktopWebView(webView)
44
79
onCreated()
45
- webView.engine.load(" https://ooni.org" )
46
80
}
47
81
}
48
82
},
49
83
modifier = modifier,
84
+ update = { jfxPanel ->
85
+ Platform .runLater {
86
+ val scene = jfxPanel.scene
87
+ val root = scene?.root as ? StackPane
88
+ val webView = root?.children?.get(0 ) as ? WebView
89
+ webView?.let {
90
+ when (event) {
91
+ is OoniWebViewController .Event .Load -> {
92
+ webView.engine.load(event.url)
93
+ }
94
+ OoniWebViewController .Event .Reload -> {
95
+ webView.engine.reload()
96
+ }
97
+ OoniWebViewController .Event .Back -> {
98
+ if (webView.engine.history.currentIndex > 0 ) {
99
+ webView.engine.history.go(- 1 )
100
+ }
101
+ }
102
+ null -> Unit
103
+ }
104
+ }
105
+ }
106
+ event?.let (controller::onEventHandled)
107
+ },
50
108
)
109
+
110
+ DisposableEffect (Unit ) {
111
+ onDispose {
112
+ currentOnDispose()
113
+ }
114
+ }
51
115
}
0 commit comments