|
@@ -0,0 +1,256 @@
|
|
|
|
+package com.vpn.fastestvpnservice.screensTV
|
|
|
|
+
|
|
|
|
+import android.util.Log
|
|
|
|
+import androidx.compose.foundation.background
|
|
|
|
+import androidx.compose.foundation.clickable
|
|
|
|
+import androidx.compose.foundation.focusable
|
|
|
|
+import androidx.compose.foundation.layout.Box
|
|
|
|
+import androidx.compose.foundation.layout.BoxScope
|
|
|
|
+import androidx.compose.foundation.layout.Column
|
|
|
|
+import androidx.compose.foundation.layout.Spacer
|
|
|
|
+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.lazy.LazyRow
|
|
|
|
+import androidx.compose.foundation.lazy.itemsIndexed
|
|
|
|
+import androidx.compose.foundation.rememberScrollState
|
|
|
|
+import androidx.compose.foundation.verticalScroll
|
|
|
|
+import androidx.compose.material.icons.Icons
|
|
|
|
+import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
|
|
+import androidx.compose.material3.Icon
|
|
|
|
+import androidx.compose.material3.IconButton
|
|
|
|
+import androidx.compose.material3.MaterialTheme
|
|
|
|
+import androidx.compose.material3.Surface
|
|
|
|
+import androidx.compose.material3.Text
|
|
|
|
+import androidx.compose.runtime.Composable
|
|
|
|
+import androidx.compose.runtime.LaunchedEffect
|
|
|
|
+import androidx.compose.runtime.getValue
|
|
|
|
+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.focus.FocusRequester
|
|
|
|
+import androidx.compose.ui.focus.focusRequester
|
|
|
|
+import androidx.compose.ui.focus.onFocusChanged
|
|
|
|
+import androidx.compose.ui.graphics.Color
|
|
|
|
+import androidx.compose.ui.platform.LocalContext
|
|
|
|
+import androidx.compose.ui.res.colorResource
|
|
|
|
+import androidx.compose.ui.unit.dp
|
|
|
|
+import androidx.navigation.NavHostController
|
|
|
|
+import com.vpn.fastestvpnservice.R
|
|
|
|
+import com.vpn.fastestvpnservice.beans.Server
|
|
|
|
+import com.vpn.fastestvpnservice.customItems.ServerItemTV
|
|
|
|
+import com.vpn.fastestvpnservice.screens.serverListViewModelSplash
|
|
|
|
+
|
|
|
|
+@Composable
|
|
|
|
+fun ServerListTV(navHostController: NavHostController) {
|
|
|
|
+ val context = LocalContext.current
|
|
|
|
+ Box(
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .fillMaxSize()
|
|
|
|
+ .background(
|
|
|
|
+ color = colorResource(id = R.color.background_color_gray)
|
|
|
|
+ )
|
|
|
|
+ .padding(bottom = 0.dp)
|
|
|
|
+
|
|
|
|
+ ) {
|
|
|
|
+ HeaderRowSL(navHostController = navHostController)
|
|
|
|
+
|
|
|
|
+ var locations = ArrayList<Server>()
|
|
|
|
+ var dedicatedIP = ArrayList<Server>()
|
|
|
|
+ var streaming = ArrayList<Server>()
|
|
|
|
+ var dvpn = ArrayList<Server>()
|
|
|
|
+ var p2p = ArrayList<Server>()
|
|
|
|
+
|
|
|
|
+ var isLocationsEnabled by remember { mutableStateOf(false) }
|
|
|
|
+ var isDedicatedIpEnabled by remember { mutableStateOf(false) }
|
|
|
|
+ var isStreamingEnabled by remember { mutableStateOf(false) }
|
|
|
|
+ var isDvpnEnabled by remember { mutableStateOf(false) }
|
|
|
|
+ var isP2pEnabled by remember { mutableStateOf(false) }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ val countries = serverListViewModelSplash.liveDataGetServersGlobal.value
|
|
|
|
+ countries?.forEachIndexed { index, serverData ->
|
|
|
|
+ Log.d("test_serverlist_tv","$index ${serverData?.name} ${serverData?.servers?.size}")
|
|
|
|
+ if (serverData?.name?.equals("Servers") == true) {
|
|
|
|
+ serverData.servers?.let { locations = it }
|
|
|
|
+ if (locations.size > 0) isLocationsEnabled = true
|
|
|
|
+ }
|
|
|
|
+ else if (serverData?.name?.equals("Dedicated IP") == true) {
|
|
|
|
+ serverData.servers?.let { dedicatedIP = it }
|
|
|
|
+ if (dedicatedIP.size > 0) isDedicatedIpEnabled = true
|
|
|
|
+ }
|
|
|
|
+ else if (serverData?.name?.equals("Streaming") == true) {
|
|
|
|
+ serverData.servers?.let { streaming = it }
|
|
|
|
+ if (streaming.size > 0) isStreamingEnabled = true
|
|
|
|
+ }
|
|
|
|
+ else if (serverData?.name?.equals("D-VPN") == true) {
|
|
|
|
+ serverData.servers?.let { dvpn = it }
|
|
|
|
+ if (dvpn.size > 0) isDvpnEnabled = true
|
|
|
|
+ }
|
|
|
|
+ else if (serverData?.name?.equals("P2P") == true) {
|
|
|
|
+ serverData.servers?.let { p2p = it }
|
|
|
|
+ if (p2p.size > 0) isP2pEnabled = true
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Column(
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .fillMaxSize()
|
|
|
|
+ .padding(top = 80.dp, start = 24.dp, end = 24.dp, bottom = 24.dp)
|
|
|
|
+ .verticalScroll(rememberScrollState())
|
|
|
|
+ .background(Color.Transparent)
|
|
|
|
+ ) {
|
|
|
|
+ val topPadding = 25.dp
|
|
|
|
+ Spacer(modifier = Modifier.height(0.dp))
|
|
|
|
+
|
|
|
|
+ if (isLocationsEnabled) {
|
|
|
|
+ Text(
|
|
|
|
+ text = "Top Locations",
|
|
|
|
+ style = MaterialTheme.typography.labelLarge,
|
|
|
|
+ color = colorResource(id = R.color.dark_blue_gray_text),
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = topPadding, start = 0.dp)
|
|
|
|
+ .focusable()
|
|
|
|
+ )
|
|
|
|
+ LazyRow(
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = 10.dp, start = 0.dp, end = 0.dp)
|
|
|
|
+ .background(Color.Transparent)
|
|
|
|
+ ) {
|
|
|
|
+ itemsIndexed(items = locations, itemContent = { index, server ->
|
|
|
|
+ ServerItemTV(server = server, navHostController = navHostController, serverPing = server.ping)
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (isDedicatedIpEnabled) {
|
|
|
|
+ Text(
|
|
|
|
+ text = "Dedicated IP",
|
|
|
|
+ style = MaterialTheme.typography.labelLarge,
|
|
|
|
+ color = colorResource(id = R.color.dark_blue_gray_text),
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = topPadding, start = 0.dp)
|
|
|
|
+ )
|
|
|
|
+ LazyRow(
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = 10.dp, start = 0.dp, end = 0.dp)
|
|
|
|
+ .background(Color.Transparent)
|
|
|
|
+ ) {
|
|
|
|
+ itemsIndexed(items = dedicatedIP, itemContent = { index, server ->
|
|
|
|
+ ServerItemTV(server = server, navHostController = navHostController, serverPing = server.ping)
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (isStreamingEnabled) {
|
|
|
|
+ Text(
|
|
|
|
+ text = "Streaming",
|
|
|
|
+ style = MaterialTheme.typography.labelLarge,
|
|
|
|
+ color = colorResource(id = R.color.dark_blue_gray_text),
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = topPadding, start = 0.dp)
|
|
|
|
+ )
|
|
|
|
+ LazyRow(
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = 10.dp, start = 0.dp, end = 0.dp)
|
|
|
|
+ .background(Color.Transparent)
|
|
|
|
+ ) {
|
|
|
|
+ itemsIndexed(items = streaming, itemContent = { index, server ->
|
|
|
|
+ ServerItemTV(server = server, navHostController = navHostController, serverPing = server.ping)
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (isDvpnEnabled) {
|
|
|
|
+ Text(
|
|
|
|
+ text = "D-VPN",
|
|
|
|
+ style = MaterialTheme.typography.labelLarge,
|
|
|
|
+ color = colorResource(id = R.color.dark_blue_gray_text),
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = topPadding, start = 0.dp)
|
|
|
|
+ )
|
|
|
|
+ LazyRow(
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = 10.dp, start = 0.dp, end = 0.dp)
|
|
|
|
+ .background(Color.Transparent)
|
|
|
|
+ ) {
|
|
|
|
+ itemsIndexed(items = dvpn, itemContent = { index, server ->
|
|
|
|
+ ServerItemTV(server = server, navHostController = navHostController, serverPing = server.ping)
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (isP2pEnabled) {
|
|
|
|
+ Text(
|
|
|
|
+ text = "P2P",
|
|
|
|
+ style = MaterialTheme.typography.labelLarge,
|
|
|
|
+ color = colorResource(id = R.color.dark_blue_gray_text),
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = topPadding, start = 0.dp)
|
|
|
|
+ )
|
|
|
|
+ LazyRow(
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = 10.dp, start = 0.dp, end = 0.dp)
|
|
|
|
+ .background(Color.Transparent)
|
|
|
|
+ ) {
|
|
|
|
+ itemsIndexed(items = p2p, itemContent = { index, server ->
|
|
|
|
+ ServerItemTV(server = server, navHostController = navHostController, serverPing = server.ping)
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+@Composable
|
|
|
|
+fun BoxScope.HeaderRowSL(
|
|
|
|
+ navHostController: NavHostController) {
|
|
|
|
+ val focusRequester1 = remember { FocusRequester() }
|
|
|
|
+ var isButtonFocused by remember { mutableStateOf(false) }
|
|
|
|
+ LaunchedEffect(key1 = Unit) {
|
|
|
|
+ focusRequester1.requestFocus()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ IconButton(
|
|
|
|
+ onClick = {
|
|
|
|
+ navHostController.popBackStack()
|
|
|
|
+ },
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .align(Alignment.TopStart)
|
|
|
|
+ .padding(top = 25.dp)
|
|
|
|
+ .padding(start = 16.dp)
|
|
|
|
+ .size(30.dp, 32.dp)
|
|
|
|
+ .background(if (isButtonFocused) Color.LightGray else Color.Transparent)
|
|
|
|
+ .focusRequester(focusRequester1)
|
|
|
|
+ .onFocusChanged {
|
|
|
|
+ isButtonFocused = it.isFocused
|
|
|
|
+ }
|
|
|
|
+ .focusable()
|
|
|
|
+ .clickable {
|
|
|
|
+ navHostController.popBackStack()
|
|
|
|
+ }
|
|
|
|
+ ) {
|
|
|
|
+ Icon(
|
|
|
|
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
|
|
|
+ contentDescription = "Arrow-Back",
|
|
|
|
+ tint = colorResource(id = R.color.dark_blue_gray_text),
|
|
|
|
+// tint = MaterialTheme.colorScheme.primary,
|
|
|
|
+ modifier = Modifier.size(30.dp, 32.dp)
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ Surface(
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .padding(top = 25.dp)
|
|
|
|
+ .height(32.dp)
|
|
|
|
+ .align(Alignment.TopCenter)
|
|
|
|
+ .padding(5.dp),
|
|
|
|
+ color = colorResource(id = R.color.transparent)
|
|
|
|
+ ) {
|
|
|
|
+ Text(text = "Locations",
|
|
|
|
+ style = MaterialTheme.typography.bodyMedium,
|
|
|
|
+// color = MaterialTheme.colorScheme.primary,
|
|
|
|
+ color = colorResource(id = R.color.dark_blue_gray_text),
|
|
|
|
+ modifier = Modifier.fillMaxHeight()
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+}
|