|
@@ -1,5 +1,9 @@
|
|
package com.vpn.fastestvpnservice.screensTV
|
|
package com.vpn.fastestvpnservice.screensTV
|
|
|
|
|
|
|
|
+import android.content.Intent
|
|
|
|
+import android.location.Location
|
|
|
|
+import android.util.Log
|
|
|
|
+import android.widget.Toast
|
|
import androidx.compose.foundation.Image
|
|
import androidx.compose.foundation.Image
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.border
|
|
import androidx.compose.foundation.border
|
|
@@ -16,17 +20,22 @@ import androidx.compose.foundation.layout.size
|
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
import androidx.compose.foundation.text.KeyboardActions
|
|
import androidx.compose.foundation.text.KeyboardActions
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
|
|
+import androidx.compose.material3.CircularProgressIndicator
|
|
import androidx.compose.material3.Icon
|
|
import androidx.compose.material3.Icon
|
|
import androidx.compose.material3.MaterialTheme
|
|
import androidx.compose.material3.MaterialTheme
|
|
import androidx.compose.material3.Scaffold
|
|
import androidx.compose.material3.Scaffold
|
|
|
|
+import androidx.compose.material3.SnackbarHostState
|
|
import androidx.compose.material3.Text
|
|
import androidx.compose.material3.Text
|
|
import androidx.compose.material3.TextField
|
|
import androidx.compose.material3.TextField
|
|
import androidx.compose.material3.TextFieldDefaults
|
|
import androidx.compose.material3.TextFieldDefaults
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.getValue
|
|
|
|
+import androidx.compose.runtime.livedata.observeAsState
|
|
|
|
+import androidx.compose.runtime.mutableFloatStateOf
|
|
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 androidx.compose.runtime.setValue
|
|
import androidx.compose.runtime.setValue
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.Modifier
|
|
@@ -46,19 +55,36 @@ import androidx.compose.ui.text.TextStyle
|
|
import androidx.compose.ui.text.input.ImeAction
|
|
import androidx.compose.ui.text.input.ImeAction
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.compose.ui.unit.dp
|
|
|
|
+import androidx.lifecycle.viewmodel.compose.viewModel
|
|
import androidx.navigation.NavHostController
|
|
import androidx.navigation.NavHostController
|
|
import androidx.tv.material3.Button
|
|
import androidx.tv.material3.Button
|
|
import androidx.tv.material3.ButtonDefaults
|
|
import androidx.tv.material3.ButtonDefaults
|
|
import androidx.tv.material3.Surface
|
|
import androidx.tv.material3.Surface
|
|
import androidx.tv.material3.SurfaceDefaults
|
|
import androidx.tv.material3.SurfaceDefaults
|
|
import com.vpn.fastestvpnservice.R
|
|
import com.vpn.fastestvpnservice.R
|
|
|
|
+import com.vpn.fastestvpnservice.beans.Server
|
|
|
|
+import com.vpn.fastestvpnservice.beans.filterList
|
|
import com.vpn.fastestvpnservice.beans.isDarkTheme
|
|
import com.vpn.fastestvpnservice.beans.isDarkTheme
|
|
|
|
+import com.vpn.fastestvpnservice.constants.smartConnect
|
|
|
|
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
|
|
|
|
+import com.vpn.fastestvpnservice.screens.serverListViewModelSplash
|
|
|
|
+import com.vpn.fastestvpnservice.sealedClass.Screen
|
|
import com.vpn.fastestvpnservice.sealedClass.ScreenTV
|
|
import com.vpn.fastestvpnservice.sealedClass.ScreenTV
|
|
import com.vpn.fastestvpnservice.ui.theme.customTypography
|
|
import com.vpn.fastestvpnservice.ui.theme.customTypography
|
|
|
|
+import com.vpn.fastestvpnservice.viewmodels.LoginViewModel
|
|
|
|
+import com.vpn.fastestvpnservice.viewmodels.SearchListViewModel
|
|
|
|
+import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
|
|
|
|
+import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
|
|
|
|
+import com.vpn.fastestvpnservice.views.CustomValidation
|
|
|
|
+import com.vpn.fastestvpnservice.views.ShowCustomSnackBar
|
|
|
|
+import com.vpn.fastestvpnservice.widgets.SimpleAppWidget
|
|
|
|
+import kotlinx.coroutines.delay
|
|
|
|
+import kotlinx.coroutines.launch
|
|
|
|
|
|
@Composable
|
|
@Composable
|
|
fun LoginTV(navHostController: NavHostController) {
|
|
fun LoginTV(navHostController: NavHostController) {
|
|
val context = LocalContext.current
|
|
val context = LocalContext.current
|
|
|
|
+ val loginViewModel: LoginViewModel = viewModel()
|
|
val keyboardController = LocalSoftwareKeyboardController.current
|
|
val keyboardController = LocalSoftwareKeyboardController.current
|
|
val focusManager = LocalFocusManager.current
|
|
val focusManager = LocalFocusManager.current
|
|
var textChanged by remember { mutableStateOf("") }
|
|
var textChanged by remember { mutableStateOf("") }
|
|
@@ -69,6 +95,7 @@ fun LoginTV(navHostController: NavHostController) {
|
|
val focusRequester1 = remember { FocusRequester() }
|
|
val focusRequester1 = remember { FocusRequester() }
|
|
val focusRequester2 = remember { FocusRequester() }
|
|
val focusRequester2 = remember { FocusRequester() }
|
|
val focusRequester3 = remember { FocusRequester() }
|
|
val focusRequester3 = remember { FocusRequester() }
|
|
|
|
+ val snackBarStateRed = remember { SnackbarHostState() }
|
|
|
|
|
|
LaunchedEffect(key1 = Unit) {
|
|
LaunchedEffect(key1 = Unit) {
|
|
focusRequester1.requestFocus()
|
|
focusRequester1.requestFocus()
|
|
@@ -84,6 +111,32 @@ fun LoginTV(navHostController: NavHostController) {
|
|
contentScale = ContentScale.FillBounds
|
|
contentScale = ContentScale.FillBounds
|
|
))
|
|
))
|
|
{
|
|
{
|
|
|
|
+ ShowCustomSnackBar(snackBarStateRed, R.color.Red, R.color.white)
|
|
|
|
+
|
|
|
|
+ if (loginViewModel.liveDataLoginStatus.value == true) {
|
|
|
|
+ Toast.makeText(context, "Inside Status", Toast.LENGTH_SHORT).show()
|
|
|
|
+ var progress by remember { mutableFloatStateOf(0.1F) }
|
|
|
|
+
|
|
|
|
+ LaunchedEffect(key1 = Unit) {
|
|
|
|
+ while (true) {
|
|
|
|
+ for (i in 1..100) {
|
|
|
|
+ progress = i.toFloat()/100F
|
|
|
|
+ delay(150)
|
|
|
|
+ }
|
|
|
|
+ progress = 0.1F
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ CircularProgressIndicator(
|
|
|
|
+ progress = { progress },
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .size(50.dp)
|
|
|
|
+ .align(Alignment.Center),
|
|
|
|
+ color = colorResource(id = R.color.yellow_text),
|
|
|
|
+ strokeWidth = 5.dp,
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+
|
|
Image(
|
|
Image(
|
|
painter = painterResource(
|
|
painter = painterResource(
|
|
id = R.drawable.fastestapp_logo3x),
|
|
id = R.drawable.fastestapp_logo3x),
|
|
@@ -238,7 +291,9 @@ fun LoginTV(navHostController: NavHostController) {
|
|
),
|
|
),
|
|
)
|
|
)
|
|
Spacer(modifier = Modifier.height(25.dp))
|
|
Spacer(modifier = Modifier.height(25.dp))
|
|
- LoginButtonTV(navHostController, focusRequester3)
|
|
|
|
|
|
+ LoginButtonTV(
|
|
|
|
+ navHostController, focusRequester3, textChanged, passwordChanged, loginViewModel, snackBarStateRed
|
|
|
|
+ )
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -246,9 +301,21 @@ fun LoginTV(navHostController: NavHostController) {
|
|
}
|
|
}
|
|
|
|
|
|
@Composable
|
|
@Composable
|
|
-fun ColumnScope.LoginButtonTV(navHostController: NavHostController,
|
|
|
|
- focusRequester3: FocusRequester) {
|
|
|
|
|
|
+fun ColumnScope.LoginButtonTV(
|
|
|
|
+ navHostController: NavHostController,
|
|
|
|
+ focusRequester3: FocusRequester,
|
|
|
|
+ email: String,
|
|
|
|
+ password: String,
|
|
|
|
+ loginViewModel: LoginViewModel,
|
|
|
|
+ snackBarStateRed: SnackbarHostState
|
|
|
|
+ )
|
|
|
|
+{
|
|
var isButtonFocused by remember { mutableStateOf(false) }
|
|
var isButtonFocused by remember { mutableStateOf(false) }
|
|
|
|
+ val context = LocalContext.current
|
|
|
|
+ val coroutineScope = rememberCoroutineScope()
|
|
|
|
+ val customValidation = CustomValidation()
|
|
|
|
+ val prefHelper = BasePreferenceHelper(context)
|
|
|
|
+
|
|
Button(
|
|
Button(
|
|
modifier = Modifier
|
|
modifier = Modifier
|
|
.background(colorResource(id = R.color.transparent))
|
|
.background(colorResource(id = R.color.transparent))
|
|
@@ -261,13 +328,53 @@ fun ColumnScope.LoginButtonTV(navHostController: NavHostController,
|
|
// .focusable()
|
|
// .focusable()
|
|
,
|
|
,
|
|
onClick = {
|
|
onClick = {
|
|
-// Toast.makeText(
|
|
|
|
-// context, "Test", Toast.LENGTH_SHORT
|
|
|
|
-// ).show()
|
|
|
|
- navHostController.popBackStack()
|
|
|
|
- navHostController.navigate(
|
|
|
|
- ScreenTV.BottomBarTV.route
|
|
|
|
- )
|
|
|
|
|
|
+ val isErrors = customValidation.isValidText(email, "Email")
|
|
|
|
+ val isError1 = customValidation.isValidText(password, "Password")
|
|
|
|
+ val isError2 = customValidation.isValidPassword(password)
|
|
|
|
+
|
|
|
|
+ if (!isErrors) {
|
|
|
|
+// ShowErrorRow(errorText = "Email is Empty")
|
|
|
|
+ coroutineScope.launch {
|
|
|
|
+ snackBarStateRed.showSnackbar("Email is Empty")
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if (!isError1) {
|
|
|
|
+// ShowErrorRow(errorText = "Password is Empty")
|
|
|
|
+ coroutineScope.launch {
|
|
|
|
+ snackBarStateRed.showSnackbar("Password is Empty")
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if (!isError2) {
|
|
|
|
+// ShowErrorRow(errorText = "Should be 3 or more!")
|
|
|
|
+ coroutineScope.launch {
|
|
|
|
+ snackBarStateRed.showSnackbar("Password should be 3 or more!")
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (loginViewModel.liveDataLoginStatus.value == false) {
|
|
|
|
+ if (customValidation.isValidText(email, "Email") &&
|
|
|
|
+ customValidation.isValidText(password, "Password") &&
|
|
|
|
+ customValidation.isValidPassword(password)) {
|
|
|
|
+
|
|
|
|
+ if (email.isNotEmpty() && password.isNotEmpty()) {
|
|
|
|
+ Toast.makeText(context, "Inside Login", Toast.LENGTH_SHORT).show()
|
|
|
|
+ loginViewModel.setLoginStatus(true)
|
|
|
|
+ loginViewModel.loginRequest(
|
|
|
|
+ email,
|
|
|
|
+ password,
|
|
|
|
+ "TV",
|
|
|
|
+ "14",
|
|
|
|
+ "3.2.9"
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// navHostController.popBackStack()
|
|
|
|
+// navHostController.navigate(
|
|
|
|
+// ScreenTV.BottomBarTV.route
|
|
|
|
+// )
|
|
},
|
|
},
|
|
shape = ButtonDefaults.shape(
|
|
shape = ButtonDefaults.shape(
|
|
shape = RoundedCornerShape(16.dp),
|
|
shape = RoundedCornerShape(16.dp),
|
|
@@ -306,13 +413,119 @@ fun ColumnScope.LoginButtonTV(navHostController: NavHostController,
|
|
modifier = Modifier
|
|
modifier = Modifier
|
|
.background(Color.Transparent)
|
|
.background(Color.Transparent)
|
|
.align(Alignment.Center),
|
|
.align(Alignment.Center),
|
|
- text = "Sign In",
|
|
|
|
|
|
+ text = "Sign In ${loginViewModel.liveDataLoginStatus.value}",
|
|
style = MaterialTheme.typography.titleMedium,
|
|
style = MaterialTheme.typography.titleMedium,
|
|
color = if (isButtonFocused) colorResource(id = R.color.blue_text) else colorResource(id = R.color.white),
|
|
color = if (isButtonFocused) colorResource(id = R.color.blue_text) else colorResource(id = R.color.white),
|
|
// color = MaterialTheme.colorScheme.primaryContainer
|
|
// color = MaterialTheme.colorScheme.primaryContainer
|
|
// textAlign = TextAlign.Center
|
|
// textAlign = TextAlign.Center
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ val loginData by loginViewModel.liveDataUserResponse.observeAsState()
|
|
|
|
+ loginData?.let { response ->
|
|
|
|
+ loginViewModel.setLoginStatus(false)
|
|
|
|
+// showLoader = false
|
|
|
|
+ if (response.status) {
|
|
|
|
+ response.data?.let {
|
|
|
|
+ prefHelper.setLoggedInState(true)
|
|
|
|
+
|
|
|
|
+ prefHelper.savePassword(password)
|
|
|
|
+ prefHelper.saveUser(it)
|
|
|
|
+ it.wireguard?.let { wg ->
|
|
|
|
+ prefHelper.saveWireGuard(wg)
|
|
|
|
+ }
|
|
|
|
+ it.product?.let { it1 -> prefHelper.saveProduct(it1) }
|
|
|
|
+ prefHelper.saveEnabledProtocols(it.enabled_protocols)
|
|
|
|
+ prefHelper.saveAvailableProtocols(it.available_protocols)
|
|
|
|
+ prefHelper.saveXPlatformToken(it.userinfo?.email + "_" + System.currentTimeMillis())
|
|
|
|
+ prefHelper.saveAdBlockState(false)
|
|
|
|
+ prefHelper.saveFilterList(filterList[0])
|
|
|
|
+ prefHelper.saveSmartList(smartConnect[0])
|
|
|
|
+
|
|
|
|
+ it.servers?.let {
|
|
|
|
+ prefHelper.saveServerData(it)
|
|
|
|
+ }
|
|
|
|
+ prefHelper.getFcmToken().let {
|
|
|
|
+ loginViewModel.sendFcmToken(it)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ val smartLocationList: MutableList<Server> = ArrayList<Server>()
|
|
|
|
+ prefHelper.getServerData().get(0).servers?.let {
|
|
|
|
+ val serverDataLocation = it
|
|
|
|
+
|
|
|
|
+ val distinctdatanotnull =
|
|
|
|
+ serverDataLocation.filter { // servers's lt and lt not be null
|
|
|
|
+ it.lt != null && it.lg != null
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ val distinctdata =
|
|
|
|
+ distinctdatanotnull.distinctBy { // servers's lt filter, no same lt of a server
|
|
|
|
+ it.lt
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ val result = FloatArray(1)
|
|
|
|
+ val ipinfo = prefHelper.getIpinfo()
|
|
|
|
+
|
|
|
|
+ distinctdata.forEachIndexed { index, server ->
|
|
|
|
+ val lat1 = ipinfo?.latitute
|
|
|
|
+ val lon1 = ipinfo?.longitude
|
|
|
|
+ val lat2 = server.lt
|
|
|
|
+ val lon2 = server.lg
|
|
|
|
+
|
|
|
|
+ if (lat1 != null && lat2 != null && lon1 != null && lon2 != null) {
|
|
|
|
+ Location.distanceBetween(lat1, lon1, lat2, lon2, result)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ val distance: Float = result[0]
|
|
|
|
+ distinctdata.get(index).distance = distance
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ val sortedDistance = distinctdata.sortedBy {
|
|
|
|
+ it.distance
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (sortedDistance.isNotEmpty()) {
|
|
|
|
+ for (i in 0..0) {
|
|
|
|
+ smartLocationList.add(sortedDistance.get(i))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ smartLocationList.forEach {
|
|
|
|
+// prefHelper.setSmartServerObject(it)
|
|
|
|
+ prefHelper.setRecommendedServerObject(it)
|
|
|
|
+ Log.d("smartLocationList", "L:: server = ${it.server_name}")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ splashViewModelSplash = viewModel {
|
|
|
|
+ SplashViewModel(context)
|
|
|
|
+ }
|
|
|
|
+ serverListViewModelSplash = viewModel {
|
|
|
|
+ ServerListViewModel(context = context)
|
|
|
|
+ }
|
|
|
|
+ searchListViewModelSplash = viewModel {
|
|
|
|
+ SearchListViewModel(context, serverListViewModelSplash, splashViewModelSplash)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ serverListViewModelSplash.setRecommendedSmartServers()
|
|
|
|
+ serverListViewModelSplash.setCountryData()
|
|
|
|
+
|
|
|
|
+ navHostController.popBackStack()
|
|
|
|
+ navHostController.navigate(ScreenTV.BottomBarTV.route)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ response.message?.let {
|
|
|
|
+// Log.d("test_login_msg", "${response.message}")
|
|
|
|
+ coroutineScope.launch {
|
|
|
|
+ snackBarStateRed.showSnackbar(it)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ loginViewModel.mutableLiveDataUserResponse.value = null
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|