|
@@ -3,8 +3,10 @@ package com.vpn.fastestvpnservice.screens.helpScreensAll
|
|
|
import android.annotation.SuppressLint
|
|
|
import android.app.Activity
|
|
|
import android.graphics.Bitmap
|
|
|
+import android.os.Build
|
|
|
import android.util.Log
|
|
|
import android.view.ViewGroup
|
|
|
+import android.webkit.WebSettings
|
|
|
import android.webkit.WebView
|
|
|
import android.webkit.WebViewClient
|
|
|
import androidx.compose.animation.animateContentSize
|
|
@@ -20,47 +22,32 @@ import androidx.compose.foundation.layout.Box
|
|
|
import androidx.compose.foundation.layout.BoxScope
|
|
|
import androidx.compose.foundation.layout.Column
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
-import androidx.compose.foundation.layout.Spacer
|
|
|
import androidx.compose.foundation.layout.fillMaxHeight
|
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
import androidx.compose.foundation.layout.size
|
|
|
-import androidx.compose.foundation.layout.width
|
|
|
-import androidx.compose.foundation.layout.wrapContentSize
|
|
|
-import androidx.compose.foundation.layout.wrapContentWidth
|
|
|
-import androidx.compose.foundation.rememberScrollState
|
|
|
-import androidx.compose.foundation.shape.RoundedCornerShape
|
|
|
-import androidx.compose.foundation.verticalScroll
|
|
|
import androidx.compose.material.Card
|
|
|
-import androidx.compose.material.ContentAlpha
|
|
|
import androidx.compose.material.Icon
|
|
|
import androidx.compose.material.IconButton
|
|
|
-import androidx.compose.material.Shapes
|
|
|
import androidx.compose.material.Surface
|
|
|
import androidx.compose.material.Text
|
|
|
-import androidx.compose.material.icons.Icons
|
|
|
-import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
|
-import androidx.compose.material.icons.filled.ArrowBack
|
|
|
-import androidx.compose.material.icons.filled.ArrowDropDown
|
|
|
import androidx.compose.material3.CircularProgressIndicator
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
import androidx.compose.runtime.Composable
|
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
|
+import androidx.compose.runtime.MutableState
|
|
|
import androidx.compose.runtime.getValue
|
|
|
import androidx.compose.runtime.mutableFloatStateOf
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
import androidx.compose.runtime.remember
|
|
|
import androidx.compose.runtime.setValue
|
|
|
-import androidx.compose.ui.AbsoluteAlignment
|
|
|
import androidx.compose.ui.Alignment
|
|
|
import androidx.compose.ui.Modifier
|
|
|
import androidx.compose.ui.draw.alpha
|
|
|
-import androidx.compose.ui.draw.drawBehind
|
|
|
import androidx.compose.ui.draw.rotate
|
|
|
import androidx.compose.ui.graphics.Color
|
|
|
-import androidx.compose.ui.graphics.drawscope.Stroke
|
|
|
import androidx.compose.ui.graphics.toArgb
|
|
|
import androidx.compose.ui.input.pointer.pointerInput
|
|
|
import androidx.compose.ui.platform.LocalConfiguration
|
|
@@ -69,9 +56,7 @@ import androidx.compose.ui.platform.LocalView
|
|
|
import androidx.compose.ui.res.colorResource
|
|
|
import androidx.compose.ui.res.painterResource
|
|
|
import androidx.compose.ui.text.TextStyle
|
|
|
-import androidx.compose.ui.text.font.FontStyle
|
|
|
import androidx.compose.ui.text.font.FontWeight
|
|
|
-import androidx.compose.ui.text.style.TextAlign
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
import androidx.compose.ui.unit.sp
|
|
@@ -82,10 +67,21 @@ import com.vpn.fastestvpnservice.R
|
|
|
import com.vpn.fastestvpnservice.beans.isDarkTheme
|
|
|
import com.vpn.fastestvpnservice.constants.AppConstant
|
|
|
import com.vpn.fastestvpnservice.constants.HelpDesc
|
|
|
-import com.vpn.fastestvpnservice.constants.HelpTitles
|
|
|
import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
|
|
|
-import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
|
|
|
+import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
|
|
|
import kotlinx.coroutines.delay
|
|
|
+import okhttp3.OkHttpClient
|
|
|
+import okhttp3.Request
|
|
|
+import java.io.IOException
|
|
|
+import java.security.SecureRandom
|
|
|
+import java.security.cert.X509Certificate
|
|
|
+import javax.net.ssl.HostnameVerifier
|
|
|
+import javax.net.ssl.SSLContext
|
|
|
+import javax.net.ssl.SSLSession
|
|
|
+import javax.net.ssl.TrustManager
|
|
|
+import javax.net.ssl.X509TrustManager
|
|
|
+
|
|
|
+var showLoader: MutableState<Boolean> = mutableStateOf(true)
|
|
|
|
|
|
@Composable
|
|
|
@SuppressLint("SetJavaScriptEnabled")
|
|
@@ -105,7 +101,6 @@ fun FAQ(navHostController: NavHostController) {
|
|
|
window.statusBarColor = MaterialTheme.colorScheme.onPrimary.toArgb()
|
|
|
window.navigationBarColor = MaterialTheme.colorScheme.onPrimary.toArgb()
|
|
|
|
|
|
- var showLoader by remember { mutableStateOf(true) }
|
|
|
ShowExpandList(navHostController = navHostController)
|
|
|
|
|
|
Box(modifier = Modifier
|
|
@@ -118,41 +113,17 @@ fun FAQ(navHostController: NavHostController) {
|
|
|
val languageIdentifier = basePreferenceHelper.getLanguage()
|
|
|
val faqUrl = if (isDarkTheme.value) "${AppConstant.BASE_WEBVIEW_URL}${languageIdentifier}/faq?skin=dark"
|
|
|
else "${AppConstant.BASE_WEBVIEW_URL}${languageIdentifier}/faq?device=ios"
|
|
|
- AndroidView(factory = {
|
|
|
- WebView(it).apply {
|
|
|
- layoutParams = ViewGroup.LayoutParams(
|
|
|
- ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
- ViewGroup.LayoutParams.MATCH_PARENT
|
|
|
- )
|
|
|
- webViewClient = WebViewClient()
|
|
|
-
|
|
|
- settings.javaScriptEnabled = true
|
|
|
-
|
|
|
- webViewClient = object : WebViewClient() {
|
|
|
- override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
|
|
- super.onPageStarted(view, url, favicon)
|
|
|
- Log.d("test_webview", "onPageStarted")
|
|
|
- showLoader = true
|
|
|
- }
|
|
|
-
|
|
|
- override fun onPageFinished(view: WebView?, url: String?) {
|
|
|
- super.onPageFinished(view, url)
|
|
|
- Log.d("test_webview", "onPageFinished")
|
|
|
- showLoader = false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-// loadUrl(faqUrl)
|
|
|
- }
|
|
|
- },
|
|
|
- update = {
|
|
|
- it.loadUrl(faqUrl)
|
|
|
- }
|
|
|
- )
|
|
|
|
|
|
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) {
|
|
|
+ Log.d("test_webview", "CustomWebView()")
|
|
|
+ CustomWebView(url = faqUrl)
|
|
|
+ } else {
|
|
|
+ Log.d("test_webview", "WebView()")
|
|
|
+ WebView(url = faqUrl)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (showLoader) {
|
|
|
+ if (showLoader.value) {
|
|
|
var progress by remember { mutableFloatStateOf(0.1F) }
|
|
|
|
|
|
LaunchedEffect(key1 = Unit) {
|
|
@@ -177,9 +148,154 @@ fun FAQ(navHostController: NavHostController) {
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+@Composable
|
|
|
+fun BoxScope.CustomWebView(url: String) {
|
|
|
+ AndroidView(factory = { context ->
|
|
|
+ val webView = WebView(context).apply {
|
|
|
+ layoutParams = ViewGroup.LayoutParams(
|
|
|
+ ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
+ ViewGroup.LayoutParams.MATCH_PARENT
|
|
|
+ )
|
|
|
+
|
|
|
+ settings.apply {
|
|
|
+ javaScriptEnabled = true
|
|
|
+ domStorageEnabled = true
|
|
|
+ loadsImagesAutomatically = true
|
|
|
+ mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
|
|
|
+ }
|
|
|
+
|
|
|
+ webViewClient = object : WebViewClient() {
|
|
|
+ override fun onReceivedSslError(
|
|
|
+ view: WebView?,
|
|
|
+ handler: android.webkit.SslErrorHandler?,
|
|
|
+ error: android.net.http.SslError?
|
|
|
+ ) {
|
|
|
+ handler?.proceed() // Bypass SSL certificate issues (for debugging)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Make the OkHttp request
|
|
|
+ loadContentWithOkHttp(webView, url)
|
|
|
+ webView
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+@Composable
|
|
|
+fun BoxScope.WebView(url: String) {
|
|
|
+ AndroidView(factory = {
|
|
|
+ WebView(it).apply {
|
|
|
+ layoutParams = ViewGroup.LayoutParams(
|
|
|
+ ViewGroup.LayoutParams.MATCH_PARENT,
|
|
|
+ ViewGroup.LayoutParams.MATCH_PARENT
|
|
|
+ )
|
|
|
+ webViewClient = WebViewClient()
|
|
|
+
|
|
|
+ settings.javaScriptEnabled = true
|
|
|
+
|
|
|
+ webViewClient = object : WebViewClient() {
|
|
|
+ override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
|
|
+ super.onPageStarted(view, url, favicon)
|
|
|
+ Log.d("test_webview", "onPageStarted")
|
|
|
+ showLoader.value = true
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onPageFinished(view: WebView?, url: String?) {
|
|
|
+ super.onPageFinished(view, url)
|
|
|
+ Log.d("test_webview", "onPageFinished")
|
|
|
+ showLoader.value = false
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+// loadUrl(url)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ update = {
|
|
|
+ Log.d("test_webview", "update")
|
|
|
+ it.loadUrl(url)
|
|
|
+ }
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+fun loadContentWithOkHttp(webView: WebView, url: String) {
|
|
|
+ val client = createUnsafeOkHttpClient()
|
|
|
+ val request = Request.Builder().url(url).build()
|
|
|
+
|
|
|
+ Log.d("test_webview", "loadContentWithOkHttp")
|
|
|
+
|
|
|
+ client.newCall(request).enqueue(object : okhttp3.Callback {
|
|
|
+ override fun onFailure(call: okhttp3.Call, e: IOException) {
|
|
|
+ showLoader.value = false
|
|
|
+ Log.d("test_webview", "onFailure")
|
|
|
+ Log.e("CustomWebView", "Failed to load URL with OkHttp: ${e.message}")
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
|
|
|
+ showLoader.value = false
|
|
|
+ Log.d("test_webview", "onResponse")
|
|
|
+
|
|
|
+ val htmlContent = response.body?.string() ?: ""
|
|
|
+ // Load the HTML content into the WebView on the main thread
|
|
|
+
|
|
|
+ webView.post {
|
|
|
+ showLoader.value = false
|
|
|
+ Log.d("test_webview", "webView.post")
|
|
|
+ webView.loadDataWithBaseURL(url, htmlContent, "text/html", "UTF-8", null)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+fun WebView.trustAllCertificates() {
|
|
|
+ try {
|
|
|
+ Log.d("test_webview", "try")
|
|
|
+ val trustAllCerts = arrayOf<TrustManager>(
|
|
|
+ object : X509TrustManager {
|
|
|
+ override fun checkClientTrusted(
|
|
|
+ chain: Array<out X509Certificate>?,
|
|
|
+ authType: String?
|
|
|
+ ) {}
|
|
|
+
|
|
|
+ override fun checkServerTrusted(
|
|
|
+ chain: Array<out X509Certificate>?,
|
|
|
+ authType: String?
|
|
|
+ ) {}
|
|
|
+
|
|
|
+ override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ val sslContext = SSLContext.getInstance("TLS")
|
|
|
+ sslContext.init(null, trustAllCerts, SecureRandom())
|
|
|
+ this.settings.javaScriptEnabled = true
|
|
|
+ // Set the SSL factory to the custom context that trusts all certificates
|
|
|
+ sslContext.socketFactory
|
|
|
+ } catch (e: Exception) {
|
|
|
+ Log.d("test_webview", "catch")
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
+fun createUnsafeOkHttpClient(): OkHttpClient {
|
|
|
+ val trustAllCerts = arrayOf<TrustManager>(
|
|
|
+ object : X509TrustManager {
|
|
|
+ override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
|
|
|
+ override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
|
|
|
+ override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
|
|
|
+ }
|
|
|
+ )
|
|
|
|
|
|
+ val sslContext = SSLContext.getInstance("TLS")
|
|
|
+ sslContext.init(null, trustAllCerts, SecureRandom())
|
|
|
+ val sslSocketFactory = sslContext.socketFactory
|
|
|
|
|
|
+ return OkHttpClient.Builder()
|
|
|
+ .sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
|
|
|
+ .hostnameVerifier(HostnameVerifier { _, _ -> true })
|
|
|
+ .build()
|
|
|
}
|
|
|
|
|
|
@Composable
|