optimize webview
This commit is contained in:
Generated
+1
@@ -0,0 +1 @@
|
|||||||
|
PSP
|
||||||
Generated
-4
@@ -10,10 +10,6 @@
|
|||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DialogSelection />
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
<SelectionState runConfigName="practice.PSP.tis">
|
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
|
||||||
<DialogSelection />
|
|
||||||
</SelectionState>
|
|
||||||
<SelectionState runConfigName="tis_app">
|
<SelectionState runConfigName="tis_app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DialogSelection />
|
<DialogSelection />
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(project(":design_system"))
|
||||||
implementation(libs.hilt.android)
|
implementation(libs.hilt.android)
|
||||||
ksp(libs.hilt.compiler)
|
ksp(libs.hilt.compiler)
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.PSP">
|
android:theme="@style/Theme.PSP"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
>
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.example.psp.di
|
||||||
|
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
object AppModule
|
||||||
@@ -2,6 +2,7 @@ package com.example.psp.screen
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.webkit.WebSettings
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
@@ -12,18 +13,20 @@ import androidx.compose.runtime.*
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
|
import com.example.design_system.util.snackbar.SnackbarController
|
||||||
|
import com.example.design_system.util.snackbar.SnackbarEvent
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun WebViewScreen(
|
fun WebViewScreen(
|
||||||
url: String,
|
url: String,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
var webView: WebView? by remember { mutableStateOf(null) }
|
var webView: WebView? by remember { mutableStateOf(null) }
|
||||||
val canGoBack = remember { mutableStateOf(false) }
|
val canGoBack = remember { mutableStateOf(false) }
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var lastBackTime by remember { mutableLongStateOf(0L) }
|
var lastBackTime by remember { mutableLongStateOf(0L) }
|
||||||
|
|
||||||
@@ -37,7 +40,9 @@ fun WebViewScreen(
|
|||||||
} else {
|
} else {
|
||||||
lastBackTime = now
|
lastBackTime = now
|
||||||
scope.launch {
|
scope.launch {
|
||||||
snackbarHostState.showSnackbar("Press back again to exit")
|
SnackbarController.sendEvent(
|
||||||
|
event = SnackbarEvent(message = "برای خروج یک بار دیگر بر روی دکمه بازگشت کلیک کنید.")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +67,6 @@ fun WebViewScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) }
|
|
||||||
) { padding ->
|
) { padding ->
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -80,13 +84,29 @@ fun WebViewScreen(
|
|||||||
canGoBack.value = view?.canGoBack() ?: false
|
canGoBack.value = view?.canGoBack() ?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings.javaScriptEnabled = true
|
|
||||||
loadUrl(url)
|
overScrollMode = android.view.View.OVER_SCROLL_NEVER
|
||||||
|
|
||||||
|
// Apply comprehensive WebView settings
|
||||||
|
settings.apply {
|
||||||
|
javaScriptEnabled = true
|
||||||
|
domStorageEnabled = true
|
||||||
|
databaseEnabled = true
|
||||||
|
cacheMode = WebSettings.LOAD_DEFAULT
|
||||||
|
loadsImagesAutomatically = true
|
||||||
|
allowFileAccess = true
|
||||||
|
useWideViewPort = true
|
||||||
|
loadWithOverviewMode = true
|
||||||
|
mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
|
||||||
|
setSupportZoom(false)
|
||||||
|
builtInZoomControls = false
|
||||||
|
displayZoomControls = false
|
||||||
|
}
|
||||||
webView = this
|
webView = this
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update = { view ->
|
update = {
|
||||||
webView = view
|
it.loadUrl(url)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.example.psp.viewmodel
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.webkit.WebSettings
|
||||||
|
import android.webkit.WebView
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class WebViewViewModel @Inject constructor(
|
||||||
|
application: Application
|
||||||
|
) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
private var _preloadedWebView: WebView? = null
|
||||||
|
val preloadedWebView: WebView?
|
||||||
|
get() = _preloadedWebView
|
||||||
|
|
||||||
|
init {
|
||||||
|
preloadWebView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun preloadWebView() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_preloadedWebView = WebView(getApplication()).apply {
|
||||||
|
overScrollMode = android.view.View.OVER_SCROLL_NEVER
|
||||||
|
webChromeClient = android.webkit.WebChromeClient()
|
||||||
|
// Apply the same settings as in WebViewScreen
|
||||||
|
settings.apply {
|
||||||
|
javaScriptEnabled = true
|
||||||
|
domStorageEnabled = true
|
||||||
|
cacheMode = WebSettings.LOAD_DEFAULT
|
||||||
|
loadsImagesAutomatically = true
|
||||||
|
allowFileAccess = true
|
||||||
|
useWideViewPort = true
|
||||||
|
loadWithOverviewMode = true
|
||||||
|
mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
|
||||||
|
setSupportZoom(false)
|
||||||
|
builtInZoomControls = false
|
||||||
|
displayZoomControls = false
|
||||||
|
}
|
||||||
|
// Load the URL to preload
|
||||||
|
loadUrl("https://tis.shift-am.ir")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
_preloadedWebView?.destroy()
|
||||||
|
_preloadedWebView = null
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
-22
@@ -2,13 +2,14 @@ package com.example.design_system
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.webkit.WebSettings
|
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableLongStateOf
|
import androidx.compose.runtime.mutableLongStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -21,8 +22,10 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import com.example.core.model.PrintEntity
|
import com.example.core.model.PrintEntity
|
||||||
import com.example.design_system.util.PspJavaScriptInterface
|
import com.example.design_system.util.PspJavaScriptInterface
|
||||||
|
import com.example.design_system.util.WebViewManager
|
||||||
import com.example.design_system.util.snackbar.SnackbarController
|
import com.example.design_system.util.snackbar.SnackbarController
|
||||||
import com.example.design_system.util.snackbar.SnackbarEvent
|
import com.example.design_system.util.snackbar.SnackbarEvent
|
||||||
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@SuppressLint("JavascriptInterface")
|
@SuppressLint("JavascriptInterface")
|
||||||
@@ -30,9 +33,7 @@ import kotlinx.coroutines.launch
|
|||||||
@Composable
|
@Composable
|
||||||
fun PspWebView(
|
fun PspWebView(
|
||||||
url: String,
|
url: String,
|
||||||
webView: WebView?,
|
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onWebView: (WebView) -> Unit,
|
|
||||||
onPayClick: (amount: Long, id: String?) -> Unit,
|
onPayClick: (amount: Long, id: String?) -> Unit,
|
||||||
onDeviceInfo: () -> String,
|
onDeviceInfo: () -> String,
|
||||||
onPrintClick: (printEntities: List<PrintEntity>) -> Unit,
|
onPrintClick: (printEntities: List<PrintEntity>) -> Unit,
|
||||||
@@ -42,7 +43,8 @@ fun PspWebView(
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var lastBackTime by remember { mutableLongStateOf(0L) }
|
var lastBackTime by remember { mutableLongStateOf(0L) }
|
||||||
var isPaymentLaunching by remember { mutableStateOf(false) }
|
var webView by remember { mutableStateOf<WebView?>(null) }
|
||||||
|
|
||||||
|
|
||||||
// Use rememberUpdatedState to ensure the bridge always calls the latest callbacks
|
// Use rememberUpdatedState to ensure the bridge always calls the latest callbacks
|
||||||
val currentOnPayClick by rememberUpdatedState(onPayClick)
|
val currentOnPayClick by rememberUpdatedState(onPayClick)
|
||||||
@@ -69,7 +71,7 @@ fun PspWebView(
|
|||||||
scope.launch {
|
scope.launch {
|
||||||
SnackbarController.sendEvent(
|
SnackbarController.sendEvent(
|
||||||
SnackbarEvent(
|
SnackbarEvent(
|
||||||
message = "Press back again to exit"
|
message = "برای خروج، دوباره بر روی بازگشت کلیک کنید."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -77,14 +79,22 @@ fun PspWebView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
webView = WebViewManager.getWebView(context)
|
||||||
|
onDispose {
|
||||||
|
webView?.let { WebViewManager.releaseWebView(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
factory = { ctx ->
|
factory = { ctx ->
|
||||||
WebView(ctx).apply {
|
(webView ?: WebViewManager.getWebView(ctx)).apply {
|
||||||
layoutParams = ViewGroup.LayoutParams(
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
)
|
)
|
||||||
|
overScrollMode = View.OVER_SCROLL_NEVER
|
||||||
webViewClient = object : WebViewClient() {
|
webViewClient = object : WebViewClient() {
|
||||||
override fun onPageFinished(view: WebView?, url: String?) {
|
override fun onPageFinished(view: WebView?, url: String?) {
|
||||||
super.onPageFinished(view, url)
|
super.onPageFinished(view, url)
|
||||||
@@ -92,27 +102,13 @@ fun PspWebView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.apply {
|
|
||||||
javaScriptEnabled = true
|
|
||||||
domStorageEnabled = true
|
|
||||||
loadWithOverviewMode = true
|
|
||||||
useWideViewPort = true
|
|
||||||
cacheMode = WebSettings.LOAD_DEFAULT
|
|
||||||
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
|
|
||||||
|
|
||||||
userAgentString =
|
|
||||||
"Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 Chrome/120.0 Mobile Safari/537.36"
|
|
||||||
}
|
|
||||||
|
|
||||||
addJavascriptInterface(bridge, "NativeBridge")
|
addJavascriptInterface(bridge, "NativeBridge")
|
||||||
|
|
||||||
|
|
||||||
loadUrl(url)
|
loadUrl(url)
|
||||||
onWebView(this)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update = { view ->
|
update = {
|
||||||
onWebView(view)
|
it.loadUrl(url)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.example.design_system.util
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import android.webkit.WebSettings
|
||||||
|
import android.webkit.WebView
|
||||||
|
import java.util.Stack
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
object WebViewManager {
|
||||||
|
|
||||||
|
private const val POOL_SIZE = 1
|
||||||
|
private val webViewPool = Stack<WebView>()
|
||||||
|
|
||||||
|
fun preload(context: Context) {
|
||||||
|
if (webViewPool.isEmpty()) {
|
||||||
|
repeat(POOL_SIZE) {
|
||||||
|
val webView = createWebView(context)
|
||||||
|
webViewPool.push(webView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getWebView(context: Context): WebView {
|
||||||
|
return if (webViewPool.isNotEmpty()) {
|
||||||
|
webViewPool.pop()
|
||||||
|
} else {
|
||||||
|
createWebView(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun releaseWebView(webView: WebView) {
|
||||||
|
if (webViewPool.size < POOL_SIZE) {
|
||||||
|
webViewPool.push(webView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
|
private fun createWebView(context: Context): WebView {
|
||||||
|
return WebView(context).apply {
|
||||||
|
setLayerType(View.LAYER_TYPE_HARDWARE, null)
|
||||||
|
settings.apply {
|
||||||
|
javaScriptEnabled = true
|
||||||
|
domStorageEnabled = true
|
||||||
|
databaseEnabled = true
|
||||||
|
cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
|
||||||
|
loadsImagesAutomatically = true
|
||||||
|
allowFileAccess = false
|
||||||
|
useWideViewPort = true
|
||||||
|
loadWithOverviewMode = true
|
||||||
|
mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
|
||||||
|
setSupportZoom(false)
|
||||||
|
builtInZoomControls = false
|
||||||
|
displayZoomControls = false
|
||||||
|
userAgentString = "Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 Chrome/120.0 Mobile Safari/537.36"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-1
@@ -6,7 +6,11 @@ plugins {
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.example.p3"
|
namespace = "com.example.p3"
|
||||||
compileSdk = 36
|
compileSdk {
|
||||||
|
version = release(36) {
|
||||||
|
minorApiLevel = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ android {
|
|||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
)
|
)
|
||||||
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|||||||
@@ -24,7 +24,10 @@
|
|||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.PSP"
|
android:theme="@style/Theme.PSP"
|
||||||
android:usesCleartextTraffic="true">
|
android:usesCleartextTraffic="true"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
|
||||||
|
>
|
||||||
<uses-library android:name="android.device" android:required="false" />
|
<uses-library android:name="android.device" android:required="false" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
package com.example.tis_app
|
package com.example.tis_app
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import com.example.design_system.util.WebViewManager
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class PspApplication : Application()
|
class PspApplication : Application() {
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
WebViewManager.preload(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -15,9 +17,10 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||||||
import com.example.core.getAndroidId
|
import com.example.core.getAndroidId
|
||||||
import com.example.core.getDeviceName
|
import com.example.core.getDeviceName
|
||||||
import com.example.design_system.PspWebView
|
import com.example.design_system.PspWebView
|
||||||
|
import com.example.design_system.util.WebViewManager
|
||||||
import com.example.tis_app.viewmodel.WebViewModel
|
import com.example.tis_app.viewmodel.WebViewModel
|
||||||
|
|
||||||
private const val tisIp = "194.59.214.243:8090"
|
private const val tisWebUrl = "https://tis.shift-am.ir"
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TisWebViewScreen(
|
fun TisWebViewScreen(
|
||||||
@@ -26,8 +29,19 @@ fun TisWebViewScreen(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var webView: WebView? by remember { mutableStateOf(null) }
|
var webView: WebView by remember { mutableStateOf(WebViewManager.getWebView(context)) }
|
||||||
var currentPaymentId by rememberSaveable { mutableStateOf<String?>(null) }
|
var currentPaymentId by rememberSaveable { mutableStateOf<String?>(null) }
|
||||||
|
var isPaymentProcessing by rememberSaveable { mutableStateOf(false) }
|
||||||
|
var isPrinting by rememberSaveable { mutableStateOf(false) }
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val deviceInfo by remember {
|
||||||
|
mutableStateOf(
|
||||||
|
viewModel.deviceInfoJson(
|
||||||
|
androidId = getAndroidId(context),
|
||||||
|
getDeviceName()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// launcher to handle POS app result
|
// launcher to handle POS app result
|
||||||
val posLauncher = rememberLauncherForActivityResult(
|
val posLauncher = rememberLauncherForActivityResult(
|
||||||
@@ -38,34 +52,40 @@ fun TisWebViewScreen(
|
|||||||
activityResult = result
|
activityResult = result
|
||||||
|
|
||||||
)
|
)
|
||||||
webView?.post {
|
|
||||||
webView?.evaluateJavascript(
|
webView.post {
|
||||||
|
webView.evaluateJavascript(
|
||||||
viewModel.postPaymentResult(paymentResultEntity = paymentResultEntity),
|
viewModel.postPaymentResult(paymentResultEntity = paymentResultEntity),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
isPaymentProcessing = false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PspWebView(
|
PspWebView(
|
||||||
url = tisIp,
|
url = tisWebUrl,
|
||||||
webView = webView,
|
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onWebView = { updatedWebView -> webView = updatedWebView },
|
|
||||||
onPayClick = { amount: Long, id: String? ->
|
onPayClick = { amount: Long, id: String? ->
|
||||||
|
if (isPaymentProcessing) return@PspWebView
|
||||||
|
isPaymentProcessing = true
|
||||||
currentPaymentId = id
|
currentPaymentId = id
|
||||||
viewModel.pay(amount)
|
viewModel.pay(amount)
|
||||||
.also(posLauncher::launch)
|
.also(posLauncher::launch)
|
||||||
},
|
},
|
||||||
onPrintClick = { printEntities ->
|
onPrintClick = { printEntities ->
|
||||||
viewModel.print(printEntities)
|
if (isPrinting) return@PspWebView
|
||||||
|
isPrinting = true
|
||||||
|
coroutineScope.launch {
|
||||||
|
try {
|
||||||
|
viewModel.print(printEntities)
|
||||||
|
} finally {
|
||||||
|
isPrinting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onDeviceInfo = {
|
onDeviceInfo = {
|
||||||
viewModel.deviceInfoJson(
|
deviceInfo
|
||||||
androidId = getAndroidId(context),
|
|
||||||
getDeviceName()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user