From 552da5be182235c8f871aa519baf78e91a2199b9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 3 Feb 2025 18:28:24 +0400 Subject: [PATCH] Updated on 2026-08-14 --- features/disclaimer/impl/build.gradle.kts | 1 + .../disclaimer/impl/ui/DisclaimerScreen.kt | 65 ++++++++++++------- .../impl/ui/DisclaimerWebViewClient.kt | 56 ++++++++++++++++ 3 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerWebViewClient.kt diff --git a/features/disclaimer/impl/build.gradle.kts b/features/disclaimer/impl/build.gradle.kts index c7d9e6d9fd..9144b3fbb0 100644 --- a/features/disclaimer/impl/build.gradle.kts +++ b/features/disclaimer/impl/build.gradle.kts @@ -44,6 +44,7 @@ dependencies { /** Other dependencies */ implementation(deps.arrow.core) + implementation(deps.timber) /** DI */ implementation(deps.hilt.android) diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt index a1b849f65f..1174e7d634 100644 --- a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt +++ b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt @@ -9,10 +9,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material3.ButtonColors import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.runtime.Composable -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity @@ -22,8 +19,9 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState import com.google.accompanist.web.WebView +import com.google.accompanist.web.WebViewNavigator +import com.google.accompanist.web.rememberWebViewNavigator import com.google.accompanist.web.rememberWebViewState -import com.google.accompanist.web.rememberWebViewStateWithHTMLData import com.tangem.core.ui.components.BottomFade import com.tangem.core.ui.components.NavigationBar3ButtonsScrim import com.tangem.core.ui.components.PrimaryButton @@ -42,6 +40,8 @@ import com.tangem.features.disclaimer.impl.entity.DisclaimerUM import com.tangem.features.disclaimer.impl.entity.DummyDisclaimer import com.tangem.features.disclaimer.impl.local.localTermsOfServices import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull +import com.tangem.utils.coroutines.JobHolder +import com.tangem.utils.coroutines.withDebounce import java.nio.charset.StandardCharsets @Composable @@ -94,35 +94,34 @@ internal fun DisclaimerScreen(state: DisclaimerUM) { private fun DisclaimerContent(url: String) { val backgroundColor = TangemTheme.colors.background.primary - val webViewStateUrl = rememberWebViewState(url) - val webViewStateData = rememberWebViewStateWithHTMLData( - data = localTermsOfServices, - mimeType = "text/html", - encoding = StandardCharsets.UTF_8.name(), - ) + val loadingTimeoutJobHolder = remember { JobHolder() } + var isLoading by remember { mutableStateOf(true) } - val webViewState by remember { - derivedStateOf { - if (webViewStateUrl.errorsForCurrentRequest.isNotEmpty()) { - webViewStateData - } else { - webViewStateUrl - } - } + val webViewState = rememberWebViewState(url) + val webViewNavigator = rememberWebViewNavigator() + val webViewClient = remember { + DisclaimerWebViewClient( + onLoadingFinished = { + loadingTimeoutJobHolder.cancel() + isLoading = false + }, + ) } Box { WebView( state = webViewState, - captureBackPresses = false, - onCreated = WebView::applySafeSettings, modifier = Modifier .fillMaxSize() .background(TangemTheme.colors.background.primary), + captureBackPresses = false, + navigator = webViewNavigator, + onCreated = WebView::applySafeSettings, + client = webViewClient, ) AnimatedVisibility( - visible = webViewState.isLoading, + visible = isLoading, label = "Loading state change animation", enter = fadeIn(), exit = fadeOut(), @@ -144,6 +143,28 @@ private fun DisclaimerContent(url: String) { } } } + + LaunchedEffect(loadingTimeoutJobHolder) { + withDebounce(jobHolder = loadingTimeoutJobHolder, timeMillis = 30_000) { + webViewNavigator.stopLoading() + + webViewNavigator.loadLocalToS() + } + } + + LaunchedEffect(webViewState.errorsForCurrentRequest) { + if (webViewState.errorsForCurrentRequest.isNotEmpty()) { + webViewNavigator.loadLocalToS() + } + } +} + +private fun WebViewNavigator.loadLocalToS() { + loadHtml( + html = localTermsOfServices, + mimeType = "text/html", + encoding = StandardCharsets.UTF_8.name(), + ) } @OptIn(ExperimentalPermissionsApi::class) diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerWebViewClient.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerWebViewClient.kt new file mode 100644 index 0000000000..c5fbbfb32b --- /dev/null +++ b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerWebViewClient.kt @@ -0,0 +1,56 @@ +package com.tangem.features.disclaimer.impl.ui + +import android.graphics.Bitmap +import android.webkit.WebResourceError +import android.webkit.WebResourceRequest +import android.webkit.WebView +import com.google.accompanist.web.AccompanistWebViewClient +import timber.log.Timber + +/** + * [AccompanistWebViewClient] for Disclaimer [WebView] + * + * @property onLoadingFinished lambda be invoked when client will get a result of loading (content or error) + * +[REDACTED_AUTHOR] + */ +internal class DisclaimerWebViewClient( + private val onLoadingFinished: () -> Unit, +) : AccompanistWebViewClient() { + + private val loadedUrls: MutableMap = mutableMapOf() + + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + super.onPageStarted(view, url, favicon) + + Timber.d("onPageStarted: $url") + + if (url != null) { + loadedUrls[url] = false + } + } + + override fun onPageFinished(view: WebView?, url: String?) { + super.onPageFinished(view, url) + + Timber.d("onPageFinished: $url") + + if (url != null && loadedUrls.containsKey(url)) { + loadedUrls[url] = true + onLoadingFinished() + } + } + + override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { + super.onReceivedError(view, request, error) + + val url = request?.url?.toString() + + Timber.d("onReceivedError: $url") + + if (url != null && loadedUrls.containsKey(url)) { + loadedUrls[url] = true + onLoadingFinished() + } + } +} \ No newline at end of file