Sfoglia il codice sorgente

Implemented Webview for screens on helpscreen and set UI/scrolling etc for TV

Khubaib 9 mesi fa
parent
commit
0b735182d8

+ 2 - 2
.idea/deploymentTargetSelector.xml

@@ -4,10 +4,10 @@
     <selectionStates>
       <SelectionState runConfigName="app">
         <option name="selectionMode" value="DROPDOWN" />
-        <DropdownSelection timestamp="2024-07-15T12:31:13.549007211Z">
+        <DropdownSelection timestamp="2024-07-18T11:16:12.497229403Z">
           <Target type="DEFAULT_BOOT">
             <handle>
-              <DeviceId pluginId="Default" identifier="serial=192.168.110.16:5555;connection=eb5344b6" />
+              <DeviceId pluginId="Default" identifier="serial=192.168.108.28:5555;connection=909aac42" />
             </handle>
           </Target>
         </DropdownSelection>

+ 260 - 0
.idea/other.xml

@@ -3,4 +3,264 @@
   <component name="ScreenshotViewer">
     <option name="frameScreenshot" value="true" />
   </component>
+  <component name="direct_access_persist.xml">
+    <option name="deviceSelectionList">
+      <list>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="27" />
+          <option name="brand" value="DOCOMO" />
+          <option name="codename" value="F01L" />
+          <option name="id" value="F01L" />
+          <option name="manufacturer" value="FUJITSU" />
+          <option name="name" value="F-01L" />
+          <option name="screenDensity" value="360" />
+          <option name="screenX" value="720" />
+          <option name="screenY" value="1280" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="28" />
+          <option name="brand" value="DOCOMO" />
+          <option name="codename" value="SH-01L" />
+          <option name="id" value="SH-01L" />
+          <option name="manufacturer" value="SHARP" />
+          <option name="name" value="AQUOS sense2 SH-01L" />
+          <option name="screenDensity" value="480" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2160" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="31" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="a51" />
+          <option name="id" value="a51" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy A51" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="akita" />
+          <option name="id" value="akita" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 8a" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="b0q" />
+          <option name="id" value="b0q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy S22 Ultra" />
+          <option name="screenDensity" value="600" />
+          <option name="screenX" value="1440" />
+          <option name="screenY" value="3088" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="32" />
+          <option name="brand" value="google" />
+          <option name="codename" value="bluejay" />
+          <option name="id" value="bluejay" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 6a" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="29" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="crownqlteue" />
+          <option name="id" value="crownqlteue" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy Note9" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="2220" />
+          <option name="screenY" value="1080" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="dm3q" />
+          <option name="id" value="dm3q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy S23 Ultra" />
+          <option name="screenDensity" value="600" />
+          <option name="screenX" value="1440" />
+          <option name="screenY" value="3088" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="felix" />
+          <option name="id" value="felix" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Fold" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="2208" />
+          <option name="screenY" value="1840" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="felix_camera" />
+          <option name="id" value="felix_camera" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Fold (Camera-enabled)" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="2208" />
+          <option name="screenY" value="1840" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="gts8uwifi" />
+          <option name="id" value="gts8uwifi" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy Tab S8 Ultra" />
+          <option name="screenDensity" value="320" />
+          <option name="screenX" value="1848" />
+          <option name="screenY" value="2960" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="husky" />
+          <option name="id" value="husky" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 8 Pro" />
+          <option name="screenDensity" value="390" />
+          <option name="screenX" value="1008" />
+          <option name="screenY" value="2244" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="30" />
+          <option name="brand" value="motorola" />
+          <option name="codename" value="java" />
+          <option name="id" value="java" />
+          <option name="manufacturer" value="Motorola" />
+          <option name="name" value="G20" />
+          <option name="screenDensity" value="280" />
+          <option name="screenX" value="720" />
+          <option name="screenY" value="1600" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="lynx" />
+          <option name="id" value="lynx" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 7a" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="31" />
+          <option name="brand" value="google" />
+          <option name="codename" value="oriole" />
+          <option name="id" value="oriole" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 6" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="panther" />
+          <option name="id" value="panther" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 7" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="31" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="q2q" />
+          <option name="id" value="q2q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy Z Fold3" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1768" />
+          <option name="screenY" value="2208" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="q5q" />
+          <option name="id" value="q5q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy Z Fold5" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1812" />
+          <option name="screenY" value="2176" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="30" />
+          <option name="brand" value="google" />
+          <option name="codename" value="r11" />
+          <option name="id" value="r11" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Watch" />
+          <option name="screenDensity" value="320" />
+          <option name="screenX" value="384" />
+          <option name="screenY" value="384" />
+          <option name="type" value="WEAR_OS" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="30" />
+          <option name="brand" value="google" />
+          <option name="codename" value="redfin" />
+          <option name="id" value="redfin" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 5" />
+          <option name="screenDensity" value="440" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2340" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="shiba" />
+          <option name="id" value="shiba" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 8" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="tangorpro" />
+          <option name="id" value="tangorpro" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Tablet" />
+          <option name="screenDensity" value="320" />
+          <option name="screenX" value="1600" />
+          <option name="screenY" value="2560" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="29" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="x1q" />
+          <option name="id" value="x1q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy S20" />
+          <option name="screenDensity" value="480" />
+          <option name="screenX" value="1440" />
+          <option name="screenY" value="3200" />
+        </PersistentDeviceSelectionData>
+      </list>
+    </option>
+  </component>
 </project>

+ 2 - 1
app/src/main/java/com/vpn/fastestvpnservice/constants/AppConstant.kt

@@ -7,7 +7,8 @@ class AppConstant {
         const val SIGN_UP_WEBVIEW_URL = "https://fastestvpn.com/buy-vpn"
         const val UPGRADE_WEBVIEW_URL = "https://fastestvpn.com/buy-vpn"
 
-        const val FAQ_WEBVIEW_URL = "https://fastestvpn.com/faq?device=ios"
+//        const val FAQ_WEBVIEW_URL = "https://fastestvpn.com/faq?device=ios"
+        const val FAQ_WEBVIEW_URL = "https://fastestvpn.com/faq?device=tv"
         const val CHANGE_PASSWORD_URL = "https://fastestvpn.com/password/reset"
         const val POLICY_WEBVIEW_URL = "https://fastestvpn.com/privacy-policy?device=ios"
         const val TERMS_WEBVIEW_URL = "https://fastestvpn.com/terms-of-service?device=ios"

+ 16 - 0
app/src/main/java/com/vpn/fastestvpnservice/navigation/BottomBarNavGraphTV.kt

@@ -19,6 +19,10 @@ import com.vpn.fastestvpnservice.screensTV.NotificationsTV
 import com.vpn.fastestvpnservice.screensTV.ServerListTV
 import com.vpn.fastestvpnservice.screensTV.SettingsTV
 import com.vpn.fastestvpnservice.screensTV.SplitTunnelingTV
+import com.vpn.fastestvpnservice.screensTV.helpScreensAll.AboutTV
+import com.vpn.fastestvpnservice.screensTV.helpScreensAll.FaqTV
+import com.vpn.fastestvpnservice.screensTV.helpScreensAll.PrivacyPolicyTV
+import com.vpn.fastestvpnservice.screensTV.helpScreensAll.TermsAndConditionsTV
 import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
 import com.vpn.fastestvpnservice.sealedClass.ScreenTV
 
@@ -68,6 +72,18 @@ fun BottomBarNavGraphTV(navHostController: NavHostController,
         composable(route = ScreenTV.NotificationTV.route) {
             NotificationsTV(navHostController = navHostController)
         }
+        composable(route = ScreenTV.FaqTV.route) {
+            FaqTV(navHostController = navHostController)
+        }
+        composable(route = ScreenTV.PrivacyPolicyTV.route) {
+            PrivacyPolicyTV(navHostController = navHostController)
+        }
+        composable(route = ScreenTV.TermsAndConditionsTV.route) {
+            TermsAndConditionsTV(navHostController = navHostController)
+        }
+        composable(route = ScreenTV.AboutTV.route) {
+            AboutTV(navHostController = navHostController)
+        }
 
         /* Again declare for login because of different -> navHostController */
 //        composable(route = Screen.Login.route) {

+ 22 - 23
app/src/main/java/com/vpn/fastestvpnservice/screensTV/HelpScreenTV.kt

@@ -6,6 +6,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.LocalOverscrollConfiguration
 import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -66,6 +67,7 @@ import com.vpn.fastestvpnservice.navigation.isHelpScreenPressed
 import com.vpn.fastestvpnservice.navigation.isThirdItemFocused
 import com.vpn.fastestvpnservice.navigation.isThirdItemPressed
 import com.vpn.fastestvpnservice.sealedClass.Screen
+import com.vpn.fastestvpnservice.sealedClass.ScreenTV
 
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
@@ -130,8 +132,9 @@ fun HelpTV(navHostController: NavHostController) {
                     text = "FAQ", navHostController = navHostController,
                     topPadding = 22.dp,
                     focusRequester1 = focusRequester1,
-                    onClick = {navHostController.navigate(
-                        Screen.FAQ.route
+                    onClick = {
+                        navHostController.navigate(
+                        ScreenTV.FaqTV.route
                     )},
                 )
                 AddRowTV(
@@ -140,7 +143,7 @@ fun HelpTV(navHostController: NavHostController) {
                     navHostController = navHostController,
                     onClick = {
                         navHostController.navigate(
-                        Screen.PrivacyPolicy.route
+                        ScreenTV.PrivacyPolicyTV.route
                     )
                     },
                 )
@@ -150,7 +153,7 @@ fun HelpTV(navHostController: NavHostController) {
                     navHostController = navHostController,
                     onClick = {
                         navHostController.navigate(
-                            Screen.TermsAndConditions.route
+                            ScreenTV.TermsAndConditionsTV.route
                         )
                     },
                 )
@@ -160,21 +163,21 @@ fun HelpTV(navHostController: NavHostController) {
                     navHostController = navHostController,
                     onClick = {
                         navHostController.navigate(
-                            Screen.About.route
-                        )
-                    },
-                )
-                AddRowTV(
-                    icon = R.drawable.faq3x,
-                    text = "Customer Support",
-                    navHostController = navHostController,
-                    onClick = {
-                        navHostController.navigate(
-                            Screen.CustomerSupport.route
+                            ScreenTV.AboutTV.route
                         )
                     },
-                    isIconTV = false
                 )
+//                AddRowTV(
+//                    icon = R.drawable.faq3x,
+//                    text = "Customer Support",
+//                    navHostController = navHostController,
+//                    onClick = {
+//                        navHostController.navigate(
+//                            Screen.CustomerSupport.route
+//                        )
+//                    },
+//                    isIconTV = false
+//                )
                 AddRowTV(
                     icon = R.drawable.customer_support3x,
                     text = "Email Us",
@@ -243,13 +246,9 @@ fun ColumnScope.AddRowTV(
                 isRowFocused = it.isFocused
             }
             .focusable()
-//            .clickable {
-//                Log.d("test_row", "Clicked Row ${onClick.toString()}")
-//                Toast.makeText(
-//                    context, text, Toast.LENGTH_SHORT
-//                ).show()
-////                onClick()
-//            }
+            .clickable {
+                onClick()
+            }
         ,
         horizontalArrangement = Arrangement.Start,
         verticalAlignment = Alignment.CenterVertically

+ 111 - 0
app/src/main/java/com/vpn/fastestvpnservice/screensTV/helpScreensAll/AboutScreenTV.kt

@@ -0,0 +1,111 @@
+package com.vpn.fastestvpnservice.screensTV.helpScreensAll
+
+import android.annotation.SuppressLint
+import android.graphics.Bitmap
+import android.util.Log
+import android.view.ViewGroup
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+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.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.navigation.NavHostController
+import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.constants.AppConstant
+import kotlinx.coroutines.delay
+
+@Composable
+@SuppressLint("SetJavaScriptEnabled")
+fun AboutTV(navHostController: NavHostController) {
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .background(colorResource(id = R.color.white))
+    ) {
+        var showLoader by remember { mutableStateOf(true) }
+        ShowExpandListTV(navHostController = navHostController, title = "About")
+
+        Box(modifier = Modifier
+            .padding(top = 60.dp)
+            .fillMaxSize()
+            .verticalScroll(rememberScrollState())
+            .background(colorResource(id = R.color.webview_background))
+        ) {
+//            val faqUrl = "${AppConstant.BASE_WEBVIEW_URL}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(AppConstant.ABOUT_WEBVIEW_URL)
+                }
+            )
+
+        }
+
+        if (showLoader) {
+            var progress by remember { mutableFloatStateOf(0.1F) }
+
+            LaunchedEffect(key1 = Unit) {
+                for (i in 1..100) {
+                    progress = i.toFloat()/100F
+                    delay(25)
+                }
+            }
+
+            Box(modifier = Modifier
+                .fillMaxSize()
+                .background(MaterialTheme.colorScheme.onPrimary)) {
+                CircularProgressIndicator(
+                    progress = progress,
+                    modifier = Modifier
+                        .align(Alignment.Center)
+                        .size(50.dp),
+                    colorResource(id = R.color.appYellow),
+                    strokeWidth = 5.dp,
+                )
+            }
+        }
+    }
+}

+ 118 - 0
app/src/main/java/com/vpn/fastestvpnservice/screensTV/helpScreensAll/FAQScreenTV.kt

@@ -0,0 +1,118 @@
+package com.vpn.fastestvpnservice.screensTV.helpScreensAll
+
+import android.annotation.SuppressLint
+import android.graphics.Bitmap
+import android.util.Log
+import android.view.ViewGroup
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+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.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material.Surface
+import androidx.compose.material.Text
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+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.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.navigation.NavHostController
+import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.beans.isDarkTheme
+import com.vpn.fastestvpnservice.constants.AppConstant
+import kotlinx.coroutines.delay
+
+@Composable
+@SuppressLint("SetJavaScriptEnabled")
+fun FaqTV(navHostController: NavHostController) {
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .background(colorResource(id = R.color.white))
+    ) {
+        var showLoader by remember { mutableStateOf(true) }
+        ShowExpandListTV(navHostController = navHostController, title = "FAQ")
+
+        Box(modifier = Modifier
+            .padding(top = 60.dp)
+            .fillMaxSize()
+            .verticalScroll(rememberScrollState())
+            .background(colorResource(id = R.color.webview_background))
+        ) {
+//            val faqUrl = "${AppConstant.BASE_WEBVIEW_URL}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(AppConstant.FAQ_WEBVIEW_URL)
+                }
+            )
+
+        }
+
+        if (showLoader) {
+            var progress by remember { mutableFloatStateOf(0.1F) }
+
+            LaunchedEffect(key1 = Unit) {
+                for (i in 1..100) {
+                    progress = i.toFloat()/100F
+                    delay(25)
+                }
+            }
+
+            Box(modifier = Modifier
+                .fillMaxSize()
+                .background(MaterialTheme.colorScheme.onPrimary)) {
+                CircularProgressIndicator(
+                    progress = progress,
+                    modifier = Modifier
+                        .align(Alignment.Center)
+                        .size(50.dp),
+                    colorResource(id = R.color.appYellow),
+                    strokeWidth = 5.dp,
+                )
+            }
+        }
+    }
+}

+ 158 - 0
app/src/main/java/com/vpn/fastestvpnservice/screensTV/helpScreensAll/PrivacyPolicyScreenTV.kt

@@ -0,0 +1,158 @@
+package com.vpn.fastestvpnservice.screensTV.helpScreensAll
+
+import android.annotation.SuppressLint
+import android.graphics.Bitmap
+import android.util.Log
+import android.view.ViewGroup
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material.Surface
+import androidx.compose.material.Text
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+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.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.navigation.NavHostController
+import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.constants.AppConstant
+import kotlinx.coroutines.delay
+
+@Composable
+@SuppressLint("SetJavaScriptEnabled")
+fun PrivacyPolicyTV(navHostController: NavHostController) {
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .background(colorResource(id = R.color.white))
+    ) {
+        var showLoader by remember { mutableStateOf(true) }
+        ShowExpandListTV(navHostController = navHostController, title = "Privacy Policy")
+
+        Box(modifier = Modifier
+            .padding(top = 60.dp)
+            .fillMaxSize()
+            .verticalScroll(rememberScrollState())
+            .background(colorResource(id = R.color.webview_background))
+        ) {
+//            val privacyUrl = "${AppConstant.BASE_WEBVIEW_URL}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(AppConstant.POLICY_WEBVIEW_URL)
+                }
+            )
+
+        }
+
+        if (showLoader) {
+            var progress by remember { mutableFloatStateOf(0.1F) }
+
+            LaunchedEffect(key1 = Unit) {
+                for (i in 1..100) {
+                    progress = i.toFloat()/100F
+                    delay(25)
+                }
+            }
+
+            Box(modifier = Modifier
+                .fillMaxSize()
+                .background(MaterialTheme.colorScheme.onPrimary)) {
+                CircularProgressIndicator(
+                    progress = progress,
+                    modifier = Modifier
+                        .align(Alignment.Center)
+                        .size(50.dp),
+                    colorResource(id = R.color.appYellow),
+                    strokeWidth = 5.dp,
+                )
+            }
+        }
+    }
+}
+
+@Composable
+fun BoxScope.ShowExpandListTV(
+    navHostController: NavHostController,
+    title: String
+) {
+//    IconButton(
+//        onClick = {
+//
+//            navHostController.popBackStack()
+//            navHostController.popBackStack()
+////                    navHostController.navigate(BottomBarScreen.Help.route)
+//        },
+//        modifier = Modifier
+//            .align(Alignment.TopStart)
+//            .padding(top = 10.dp)
+//            .padding(start = 16.dp)
+//            .size(30.dp, 32.dp)
+//    ) {
+//        Icon(
+//            painter = painterResource(id = R.drawable.backarrow3x),
+//            contentDescription = "Arrow-Back",
+//            tint = MaterialTheme.colorScheme.primary,
+//            modifier = Modifier.size(18.dp, 12.dp)
+//        )
+//    }
+    Surface(
+        modifier = Modifier
+            .padding(start = 14.dp, top = 16.dp)
+            .height(32.dp)
+            .align(Alignment.TopStart)
+        ,
+        color = colorResource(id = R.color.transparent)
+    ) {
+        Text(text = title,
+            color = colorResource(id = R.color.dark_blue_gray_text),
+            style = MaterialTheme.typography.bodyMedium,
+            modifier = Modifier.fillMaxHeight()
+
+        )
+    }
+}

+ 110 - 0
app/src/main/java/com/vpn/fastestvpnservice/screensTV/helpScreensAll/TermsAndConditionsScreenTV.kt

@@ -0,0 +1,110 @@
+package com.vpn.fastestvpnservice.screensTV.helpScreensAll
+
+import android.annotation.SuppressLint
+import android.graphics.Bitmap
+import android.util.Log
+import android.view.ViewGroup
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+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.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.navigation.NavHostController
+import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.constants.AppConstant
+import kotlinx.coroutines.delay
+
+@Composable
+@SuppressLint("SetJavaScriptEnabled")
+fun TermsAndConditionsTV(navHostController: NavHostController) {
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .background(colorResource(id = R.color.white))
+    ) {
+        var showLoader by remember { mutableStateOf(true) }
+        ShowExpandListTV(navHostController = navHostController, title = "Terms & Conditions")
+
+        Box(modifier = Modifier
+            .padding(top = 60.dp)
+            .fillMaxSize()
+            .verticalScroll(rememberScrollState())
+            .background(colorResource(id = R.color.webview_background))
+        ) {
+            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(AppConstant.TERMS_WEBVIEW_URL)
+                }
+            )
+
+        }
+
+        if (showLoader) {
+            var progress by remember { mutableFloatStateOf(0.1F) }
+
+            LaunchedEffect(key1 = Unit) {
+                for (i in 1..100) {
+                    progress = i.toFloat()/100F
+                    delay(25)
+                }
+            }
+
+            Box(modifier = Modifier
+                .fillMaxSize()
+                .background(MaterialTheme.colorScheme.onPrimary)) {
+                CircularProgressIndicator(
+                    progress = progress,
+                    modifier = Modifier
+                        .align(Alignment.Center)
+                        .size(50.dp),
+                    colorResource(id = R.color.appYellow),
+                    strokeWidth = 5.dp,
+                )
+            }
+        }
+    }
+}

+ 4 - 0
app/src/main/java/com/vpn/fastestvpnservice/sealedClass/ScreenTV.kt

@@ -8,4 +8,8 @@ sealed class ScreenTV(val route: String) {
     data object ServerListTV : ScreenTV("server_list_route")
     data object SplitTunnelingTV : ScreenTV("split_tunneling_tv")
     data object NotificationTV : ScreenTV("notification_tv")
+    data object FaqTV : ScreenTV("faq_tv")
+    data object PrivacyPolicyTV : ScreenTV("privacy_policy_tv")
+    data object TermsAndConditionsTV : ScreenTV("terms_and_conditions_tv")
+    data object AboutTV : ScreenTV("about_tv")
 }