@@ -2,7 +2,9 @@ package to.bitkit.ui.screens.shop
22
33import android.annotation.SuppressLint
44import android.graphics.Bitmap
5+ import android.util.Log
56import android.view.ViewGroup
7+ import android.webkit.JavascriptInterface
68import android.webkit.WebResourceError
79import android.webkit.WebResourceRequest
810import android.webkit.WebView
@@ -21,6 +23,9 @@ import androidx.compose.ui.Modifier
2123import androidx.compose.ui.res.stringResource
2224import androidx.compose.ui.tooling.preview.Preview
2325import androidx.compose.ui.viewinterop.AndroidView
26+ import kotlinx.serialization.SerialName
27+ import kotlinx.serialization.Serializable
28+ import kotlinx.serialization.json.Json
2429import to.bitkit.R
2530import to.bitkit.env.Env
2631import to.bitkit.ui.scaffold.AppTopBar
@@ -29,16 +34,51 @@ import to.bitkit.ui.scaffold.ScreenColumn
2934import to.bitkit.ui.theme.AppThemeSurface
3035import to.bitkit.utils.Logger
3136
37+ @Serializable
38+ data class WebViewMessage (
39+ val event : String ,
40+ @SerialName(" paymentUri" )
41+ val paymentUri : String? = null
42+ )
43+
3244@SuppressLint(" SetJavaScriptEnabled" )
3345@Composable
3446fun ShopWebViewScreen (
3547 onClose : () -> Unit ,
3648 onBack : () -> Unit ,
49+ onPaymentIntent : (String ) -> Unit ,
3750 page : String ,
3851) {
3952 var isLoading by remember { mutableStateOf(true ) }
4053 var webView: WebView ? by remember { mutableStateOf(null ) }
4154
55+ // Create a JavaScript interface for message handling
56+ class WebViewInterface {
57+ @JavascriptInterface
58+ fun postMessage (message : String ) {
59+ try {
60+ val json = Json { ignoreUnknownKeys = true }
61+ val data = json.decodeFromString<WebViewMessage >(message)
62+
63+ Log .d(" WebView" , " Received message: $message " )
64+
65+ when (data.event) {
66+ " payment_intent" -> {
67+ data.paymentUri?.let { uri ->
68+ onPaymentIntent(uri)
69+ }
70+ }
71+ // Add more event types as needed
72+ else -> {
73+ Log .d(" WebView" , " Unknown event type: ${data.event} " )
74+ }
75+ }
76+ } catch (e: Exception ) {
77+ Log .e(" WebView" , " Error parsing message: $message " , e)
78+ }
79+ }
80+ }
81+
4282 ScreenColumn {
4383 AppTopBar (
4484 titleText = stringResource(R .string.other__shop__discover__nav_title),
@@ -55,6 +95,7 @@ fun ShopWebViewScreen(
5595 ViewGroup .LayoutParams .MATCH_PARENT ,
5696 ViewGroup .LayoutParams .MATCH_PARENT ,
5797 )
98+
5899 webViewClient = object : WebViewClient () {
59100 override fun onPageStarted (view : WebView ? , url : String? , favicon : Bitmap ? ) {
60101 super .onPageStarted(view, url, favicon)
@@ -64,6 +105,27 @@ fun ShopWebViewScreen(
64105 override fun onPageFinished (view : WebView ? , url : String? ) {
65106 super .onPageFinished(view, url)
66107 isLoading = false
108+
109+ // Inject JavaScript to bridge postMessage to Android
110+ view?.evaluateJavascript("""
111+ window.ReactNativeWebView = {
112+ postMessage: function(data) {
113+ Android.postMessage(data);
114+ }
115+ };
116+
117+ // Override the default postMessage if it exists
118+ if (window.postMessage) {
119+ window.originalPostMessage = window.postMessage;
120+ window.postMessage = function(data) {
121+ if (typeof data === 'string') {
122+ Android.postMessage(data);
123+ } else {
124+ Android.postMessage(JSON.stringify(data));
125+ }
126+ };
127+ }
128+ """ .trimIndent(), null )
67129 }
68130
69131 override fun onReceivedError (
@@ -74,16 +136,28 @@ fun ShopWebViewScreen(
74136 super .onReceivedError(view, request, error)
75137 Logger .warn(" Error: ${error?.description} , Code: ${error?.errorCode} , URL: ${request?.url} " , context = " ShopWebViewScreen" )
76138 isLoading = false
139+
77140 error?.let {
78141 if (it.errorCode == WebViewClient .ERROR_HOST_LOOKUP ||
79142 it.errorCode == WebViewClient .ERROR_CONNECT ||
80- it.errorCode == WebViewClient .ERROR_TIMEOUT ) {
143+ it.errorCode == WebViewClient .ERROR_TIMEOUT ||
144+ it.errorCode == WebViewClient .ERROR_FILE_NOT_FOUND ) {
81145 onClose()
82146 }
83147 }
84148 }
85149 }
86- settings.javaScriptEnabled = true
150+
151+ // Configure WebView settings
152+ settings.apply {
153+ javaScriptEnabled = true
154+ domStorageEnabled = true
155+ allowContentAccess = true
156+ allowFileAccess = false
157+ }
158+
159+ addJavascriptInterface(WebViewInterface (), " Android" )
160+
87161 loadUrl(Env .buildBitrefillUri(page = page))
88162 webView = this
89163 }
@@ -114,6 +188,8 @@ private fun Preview() {
114188 ShopWebViewScreen (
115189 onClose = {},
116190 onBack = {},
191+ onPaymentIntent = { uri ->
192+ },
117193 page = " esims" ,
118194 )
119195 }
0 commit comments