HomeScreenTV.kt 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  1. package com.vpn.fastestvpnservice.screensTV
  2. //import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.act
  3. import android.content.Context
  4. import android.os.Build
  5. import android.util.Log
  6. import android.widget.Toast
  7. import androidx.compose.foundation.BorderStroke
  8. import androidx.compose.foundation.Image
  9. import androidx.compose.foundation.background
  10. import androidx.compose.foundation.border
  11. import androidx.compose.foundation.clickable
  12. import androidx.compose.foundation.focusable
  13. import androidx.compose.foundation.interaction.MutableInteractionSource
  14. import androidx.compose.foundation.layout.Arrangement
  15. import androidx.compose.foundation.layout.Box
  16. import androidx.compose.foundation.layout.BoxScope
  17. import androidx.compose.foundation.layout.Column
  18. import androidx.compose.foundation.layout.ColumnScope
  19. import androidx.compose.foundation.layout.Row
  20. import androidx.compose.foundation.layout.RowScope
  21. import androidx.compose.foundation.layout.Spacer
  22. import androidx.compose.foundation.layout.fillMaxHeight
  23. import androidx.compose.foundation.layout.fillMaxSize
  24. import androidx.compose.foundation.layout.fillMaxWidth
  25. import androidx.compose.foundation.layout.height
  26. import androidx.compose.foundation.layout.padding
  27. import androidx.compose.foundation.layout.size
  28. import androidx.compose.foundation.shape.CircleShape
  29. import androidx.compose.foundation.shape.RoundedCornerShape
  30. import androidx.compose.foundation.text.ClickableText
  31. import androidx.compose.material3.Button
  32. import androidx.compose.material3.ButtonDefaults
  33. import androidx.compose.material3.Icon
  34. import androidx.compose.material3.IconButton
  35. import androidx.compose.material3.MaterialTheme
  36. import androidx.compose.material3.Surface
  37. import androidx.compose.material3.Text
  38. import androidx.compose.runtime.Composable
  39. import androidx.compose.runtime.DisposableEffect
  40. import androidx.compose.runtime.LaunchedEffect
  41. import androidx.compose.runtime.MutableState
  42. import androidx.compose.runtime.getValue
  43. import androidx.compose.runtime.livedata.observeAsState
  44. import androidx.compose.runtime.mutableStateOf
  45. import androidx.compose.runtime.remember
  46. import androidx.compose.runtime.rememberCoroutineScope
  47. import androidx.compose.runtime.rememberUpdatedState
  48. import androidx.compose.runtime.saveable.rememberSaveable
  49. import androidx.compose.runtime.setValue
  50. import androidx.compose.ui.Alignment
  51. import androidx.compose.ui.Modifier
  52. import androidx.compose.ui.draw.alpha
  53. import androidx.compose.ui.draw.clip
  54. import androidx.compose.ui.draw.paint
  55. import androidx.compose.ui.focus.FocusRequester
  56. import androidx.compose.ui.focus.focusRequester
  57. import androidx.compose.ui.focus.onFocusChanged
  58. import androidx.compose.ui.graphics.Color
  59. import androidx.compose.ui.graphics.ColorFilter
  60. import androidx.compose.ui.graphics.painter.Painter
  61. import androidx.compose.ui.input.key.Key
  62. import androidx.compose.ui.input.key.KeyEventType
  63. import androidx.compose.ui.input.key.key
  64. import androidx.compose.ui.input.key.onKeyEvent
  65. import androidx.compose.ui.input.key.type
  66. import androidx.compose.ui.layout.ContentScale
  67. import androidx.compose.ui.platform.LocalContext
  68. import androidx.compose.ui.platform.LocalLifecycleOwner
  69. import androidx.compose.ui.res.colorResource
  70. import androidx.compose.ui.res.painterResource
  71. import androidx.compose.ui.text.AnnotatedString
  72. import androidx.compose.ui.text.TextStyle
  73. import androidx.compose.ui.unit.TextUnit
  74. import androidx.compose.ui.unit.dp
  75. import androidx.compose.ui.unit.sp
  76. import androidx.constraintlayout.compose.ConstraintLayout
  77. import androidx.constraintlayout.compose.Dimension
  78. import androidx.lifecycle.Lifecycle
  79. import androidx.lifecycle.LifecycleEventObserver
  80. import androidx.lifecycle.LifecycleOwner
  81. import androidx.lifecycle.viewmodel.compose.viewModel
  82. import androidx.navigation.NavHostController
  83. import com.vpn.fastestvpnservice.MainActivity
  84. import com.vpn.fastestvpnservice.R
  85. import com.vpn.fastestvpnservice.beans.Protocol
  86. import com.vpn.fastestvpnservice.beans.Server
  87. import com.vpn.fastestvpnservice.beans.isDarkTheme
  88. import com.vpn.fastestvpnservice.beans.toChangeServer
  89. import com.vpn.fastestvpnservice.constants.smartConnect
  90. import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
  91. import com.vpn.fastestvpnservice.interfaces.ServerCallbacksTV
  92. import com.vpn.fastestvpnservice.navigation.isFirstItemPressed
  93. import com.vpn.fastestvpnservice.navigation.isHomeScreenPressed
  94. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.ShowProtocolDialog
  95. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.ShowServerDialog
  96. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.isServerDialog
  97. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.navHostController1
  98. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.protocolObj
  99. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.serverObj
  100. import com.vpn.fastestvpnservice.screens.serverListViewModelSplash
  101. import com.vpn.fastestvpnservice.sealedClass.ScreenTV
  102. import com.vpn.fastestvpnservice.ui.theme.customTypography
  103. import com.vpn.fastestvpnservice.utils.Utils
  104. import com.vpn.fastestvpnservice.utils.VPNConnectionsUtil
  105. import com.vpn.fastestvpnservice.utils.isTablet
  106. import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
  107. import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
  108. import de.blinkt.openvpn.core.App
  109. lateinit var vpnConnectionsUtil: VPNConnectionsUtil
  110. var isProtocolDialog: MutableState<Boolean> = mutableStateOf(false)
  111. var isLocationsEnabled: MutableState<Boolean> = mutableStateOf(false)
  112. var isDedicatedIpEnabled: MutableState<Boolean> = mutableStateOf(false)
  113. var isStreamingEnabled: MutableState<Boolean> = mutableStateOf(false)
  114. var isDvpnEnabled: MutableState<Boolean> = mutableStateOf(false)
  115. var isP2pEnabled: MutableState<Boolean> = mutableStateOf(false)
  116. var locations: MutableList<Server> = ArrayList<Server>()
  117. var dedicatedIP: MutableList<Server> = ArrayList<Server>()
  118. var streaming: MutableList<Server> = ArrayList<Server>()
  119. var dvpn: MutableList<Server> = ArrayList<Server>()
  120. var p2p: MutableList<Server> = ArrayList<Server>()
  121. val onServerTV = object : ServerCallbacksTV {
  122. @Composable
  123. override fun onServerSelected(
  124. context: Context, homeViewModel: HomeViewModel,
  125. onClick: () -> Unit, isServerDialogShown: Boolean, server: Server
  126. ) {
  127. // val wg = VPNConnectionsUtil(context, act ,homeViewModel)
  128. val basePreferenceHelper = BasePreferenceHelper(context)
  129. // val serverListViewModel: ServerListViewModel = viewModel{
  130. // ServerListViewModel(context)
  131. // }
  132. Log.d("ServerCallbacks", "onServerSelected called!")
  133. val lastServer = basePreferenceHelper.getConnectedServer()
  134. val connectState = basePreferenceHelper.getConnectState()
  135. if (isServerDialogShown) {
  136. Log.d("ServerCallbacks", "onServerSelected true!")
  137. if (connectState == 2) {
  138. Log.d("ServerCallbacks", "onServerSelected isVPNConnected!")
  139. if (lastServer?.id != server.id) {
  140. isServerDialog.value = true
  141. serverObj.value = server
  142. }
  143. else {
  144. basePreferenceHelper.setConnectedServer(server)
  145. basePreferenceHelper.setServerObject(server)
  146. }
  147. } else {
  148. serverListViewModelSplash.setRecentlyConnectedServer(server)
  149. // val recentList = basePreferenceHelper.getRecentlyList()
  150. // val tempList = ArrayList<Server>()
  151. // recentList?.let { tempList.addAll(it) }
  152. //
  153. // if (tempList.size == 0) {
  154. // tempList.add(server)
  155. // }
  156. // else {
  157. // if (!tempList.any {
  158. // it.id == server.id
  159. // }) {
  160. // if (tempList.size != 5 && tempList.size < 5) {
  161. // tempList.add(0, server)
  162. // }
  163. // }
  164. // }
  165. //
  166. // basePreferenceHelper.setRecentlyList(tempList)
  167. basePreferenceHelper.setConnectedServer(server)
  168. basePreferenceHelper.setServerObject(server)
  169. // wg.startVpn()
  170. }
  171. }
  172. else {
  173. // wg.startVpn()
  174. }
  175. MainActivity.isSelectedServersShown = true
  176. onClick()
  177. }
  178. override fun onChangeProtocol(
  179. protocol: Protocol,
  180. context: Context,
  181. serverListViewModel: ServerListViewModel
  182. ) {
  183. val prefHelper = BasePreferenceHelper(context)
  184. // val wg = VPNConnectionsUtil(context, act , homeViewModel1)
  185. protocolObj.value = protocol
  186. val connectState = prefHelper.getConnectState()
  187. if (getEnableProtocols(protocol.title, prefHelper)) {
  188. Log.d("OnChangeProtocol", "getEnableProtocols yes!")
  189. if (prefHelper.getProtocol().index != protocol.index) {
  190. if (connectState == 2) {
  191. navHostController1.popBackStack()
  192. isProtocolDialog.value = true
  193. }
  194. else {
  195. prefHelper.saveProtocol(protocol = protocol)
  196. val lastServer = prefHelper.getConnectedServer()
  197. val serverList = prefHelper.getServerData()
  198. // val serverList = serverListViewModelSplash.liveDataGetServersGlobal.value
  199. if (lastServer != null) {
  200. val serverProtocol = serverListViewModel.getFilteredServerByProtocolChanged(serverList, lastServer, protocol)
  201. if (serverProtocol.isFound) {
  202. prefHelper.setServerObject(serverProtocol.server)
  203. val lastServer1 = prefHelper.getServerObject()
  204. }
  205. }
  206. serverListViewModelSplash.setCountryDataTV()
  207. }
  208. }
  209. }
  210. else {
  211. // Screen.Subscription.isTrue = true
  212. // navHostController1.let {
  213. // it.navigate(Screen.Subscription.route)
  214. // }
  215. Toast.makeText(context, "Protocol not enabled", Toast.LENGTH_SHORT).show()
  216. }
  217. }
  218. }
  219. @Composable
  220. fun HomeTV(navHostController: NavHostController, settingsNavHostController: NavHostController) {
  221. val context = LocalContext.current
  222. val basePreferenceHelper = BasePreferenceHelper(context)
  223. val prefHelper = BasePreferenceHelper(context)
  224. val scope = rememberCoroutineScope()
  225. val homeViewModel: HomeViewModel = viewModel{
  226. HomeViewModel(context, scope)
  227. }
  228. var isConnect: Int? = homeViewModel.isConnect.observeAsState().value
  229. isConnect = basePreferenceHelper.getConnectState()
  230. val focusRequester1 = remember { FocusRequester() }
  231. val focusRequester2 = remember { FocusRequester() }
  232. val focusRequester3 = remember { FocusRequester() }
  233. var isButtonFocused by remember { mutableStateOf(false) }
  234. OnLifecycleEvent { owner, event ->
  235. when (event) {
  236. Lifecycle.Event.ON_RESUME -> {
  237. Log.d("test_home_resume", "ON_RESUME: Home Screen!")
  238. // try {
  239. // App.backend?.runningTunnelNames
  240. // } catch (e: Exception) {
  241. // val back = GoBackend(context)
  242. // App.setBackend(back)
  243. // App.backend = App.getBackend()
  244. // }
  245. // vpnConnectionsUtil.onResumeCallBack()
  246. homeViewModel.getIp()
  247. // var filterServerByConnectionCount = Server()
  248. // if (prefHelper.getServerObject() != null) {
  249. // prefHelper.getServerObject()?.let {
  250. // filterServerByConnectionCount = it
  251. // }
  252. // } else {
  253. // val smartServer = basePreferenceHelper.getSmartServerObject()
  254. // smartServer?.let {
  255. // filterServerByConnectionCount = it
  256. // }
  257. // }
  258. //
  259. // server = filterServerByConnectionCount
  260. //
  261. //// splashViewModel.serverDataApi()
  262. homeViewModel.validatePassword(
  263. prefHelper.getUser()?.userinfo?.email.toString(),
  264. prefHelper.getPassword().toString(),
  265. "TV",
  266. Build.VERSION.RELEASE
  267. )
  268. }
  269. Lifecycle.Event.ON_PAUSE -> {
  270. Log.d("test_home_resume", "ON_PAUSE: Home Screen!")
  271. // vpnConnectionsUtil.onPauseCallBack()
  272. }
  273. Lifecycle.Event.ON_STOP -> {
  274. Log.d("test_home_resume", "ON_STOP: Home Screen!")
  275. // vpnConnectionsUtil.onStopCallBack()
  276. }
  277. Lifecycle.Event.ON_DESTROY -> {
  278. Log.d("test_home_resume", "ON_DESTROY: Home Screen!")
  279. // vpnConnectionsUtil.onPauseCallBack()
  280. }
  281. else -> {
  282. Log.d("test_home_resume", "else: Home Screen!")
  283. }
  284. }
  285. }
  286. val validateResponse = homeViewModel.liveDataValidate.observeAsState().value
  287. validateResponse?.let {
  288. Log.d("test_api_validate", "home => ${it.status} ${it.message}")
  289. if (!it.status) {
  290. basePreferenceHelper.setLoggedInState(false)
  291. basePreferenceHelper.clearAllData()
  292. settingsNavHostController.popBackStack()
  293. settingsNavHostController.navigate(ScreenTV.LoginTV.route)
  294. }
  295. homeViewModel._mutableLiveDataValidate.value = null
  296. }
  297. if (isHomeScreenPressed.value) {
  298. LaunchedEffect(key1 = Unit) {
  299. focusRequester1.requestFocus()
  300. }
  301. isHomeScreenPressed.value = false
  302. }
  303. var isLaunched by rememberSaveable { mutableStateOf(true) }
  304. if (isLaunched) {
  305. Log.d("test_launch","liveDataGetServersGlobal")
  306. val countries = serverListViewModelSplash.liveDataGetServersGlobal.value
  307. countries?.forEachIndexed { index, serverData ->
  308. Log.d("test_serverlist_tv","$index ${serverData?.name} ${serverData?.servers?.size}")
  309. if (serverData?.name?.equals("Servers") == true) {
  310. serverData.servers?.let { locations = it }
  311. if (locations.size > 0) isLocationsEnabled.value = true
  312. }
  313. else if (serverData?.name?.equals("Dedicated IP") == true) {
  314. serverData.servers?.let { dedicatedIP = it }
  315. if (dedicatedIP.size > 0) isDedicatedIpEnabled.value = true
  316. }
  317. else if (serverData?.name?.equals("Streaming") == true) {
  318. serverData.servers?.let { streaming = it }
  319. if (streaming.size > 0) isStreamingEnabled.value = true
  320. }
  321. else if (serverData?.name?.equals("D-VPN") == true) {
  322. serverData.servers?.let { dvpn = it }
  323. if (dvpn.size > 0) isDvpnEnabled.value = true
  324. }
  325. else if (serverData?.name?.equals("P2P") == true) {
  326. serverData.servers?.let { p2p = it }
  327. if (p2p.size > 0) isP2pEnabled.value = true
  328. }
  329. }
  330. isLaunched = false
  331. }
  332. // BackHandler {
  333. // Toast.makeText(
  334. // context, "BackHandler Home TV", Toast.LENGTH_SHORT
  335. // ).show()
  336. // }
  337. Column(
  338. modifier = Modifier
  339. .background(colorResource(id = R.color.background_color_gray))
  340. .fillMaxSize(),
  341. ) {
  342. if (isServerDialog.value) {
  343. ShowServerDialog(
  344. basePreferenceHelper,
  345. com.vpn.fastestvpnservice.screens.bottomNavBarScreens.vpnConnectionsUtil
  346. )
  347. }
  348. if (isProtocolDialog.value) {
  349. ShowProtocolDialog(
  350. basePreferenceHelper,
  351. com.vpn.fastestvpnservice.screens.bottomNavBarScreens.vpnConnectionsUtil,
  352. serverListViewModelSplash
  353. )
  354. }
  355. // 1st box
  356. ConstraintLayout(modifier = Modifier
  357. .fillMaxSize()
  358. .weight(0.6f)
  359. .background(Color.Transparent)
  360. )
  361. {
  362. val (firstComposable, secondComposable) = createRefs()
  363. val guideline = createGuidelineFromTop(0.7f)
  364. Box(
  365. modifier = Modifier
  366. .constrainAs(firstComposable) {
  367. top.linkTo(parent.top)
  368. bottom.linkTo(guideline)
  369. start.linkTo(parent.start)
  370. end.linkTo(parent.end)
  371. width = Dimension.fillToConstraints
  372. height = Dimension.fillToConstraints
  373. }
  374. .background(Color.Transparent)
  375. ) {
  376. Image(
  377. modifier = Modifier
  378. .fillMaxWidth()
  379. .fillMaxHeight()
  380. .padding(top = 0.dp),
  381. // painter = if (isConnect == App.CONNECTED) blueBackgroundTV() else pinkBackgroundTV(),
  382. painter = if (isConnect == App.CONNECTED) painterResource(id = R.drawable.bluebackground3x)
  383. else painterResource(id = R.drawable.pinkbackground3x),
  384. contentDescription = "Background Color",
  385. contentScale = ContentScale.FillBounds,
  386. )
  387. Image(
  388. modifier = Modifier
  389. .fillMaxWidth()
  390. .fillMaxHeight()
  391. .padding(bottom = 0.dp)
  392. // .alpha(if (isDarkTheme.value) 0.1F else 0.6F),
  393. .alpha(0.6F),
  394. painter = painterResource(id = R.drawable.map_home3x),
  395. contentDescription = "Home Map",
  396. contentScale = ContentScale.FillWidth,
  397. )
  398. Column(
  399. modifier = Modifier
  400. .fillMaxWidth()
  401. .fillMaxHeight()
  402. .padding(bottom = 85.dp)
  403. // .offset(y = -(118).dp)
  404. .background(Color.Transparent),
  405. horizontalAlignment = Alignment.CenterHorizontally,
  406. verticalArrangement = Arrangement.Bottom
  407. ) {
  408. val serverObj = basePreferenceHelper.getConnectedServer()
  409. val serverDis = basePreferenceHelper.getIpinfo()
  410. var ipInfo = homeViewModel.mutableLiveDataIpInfo.observeAsState().value?.query
  411. ipInfo = if (isConnect == App.CONNECTED) serverObj?.ip.toString() else serverDis?.query
  412. AddText(
  413. text = "IP ${ipInfo ?: ""}",
  414. size = 18.sp,
  415. // color = MaterialTheme.colorScheme.primary,
  416. color = colorResource(id = R.color.dark_blue_gray_text),
  417. style = MaterialTheme.typography.customTypography.headlineLarge.copy(
  418. fontSize = 18.sp
  419. )
  420. )
  421. Row(
  422. verticalAlignment = Alignment.CenterVertically,
  423. modifier = Modifier
  424. .background(Color.Transparent)
  425. .padding(top = 5.dp)
  426. ) {
  427. if (isConnect == App.CONNECTED) {
  428. val image = Utils.getDrawable(context, serverObj?.iso)
  429. if (image != 0) {
  430. Image(
  431. painter = painterResource(id = image),
  432. contentDescription = "Country",
  433. modifier = Modifier
  434. .padding(end = 6.dp)
  435. .size(15.dp)
  436. .clip(CircleShape)
  437. .paint(
  438. painter = painterResource(id = image),
  439. contentScale = ContentScale.FillBounds
  440. )
  441. )
  442. }
  443. AddText(
  444. text = "${serverObj?.server_name ?: ""}, ${serverObj?.country ?: ""}",
  445. size = 16.sp,
  446. color = colorResource(id = R.color.dark_blue_gray_text),
  447. isTablet()
  448. )
  449. } else {
  450. val image = Utils.getDrawable(context, serverDis?.countryCode)
  451. Log.d("image_logo", "$image ${serverDis?.countryCode}")
  452. if (image != 0) {
  453. Image(
  454. painter = painterResource(id = image),
  455. contentDescription = "Server",
  456. modifier = Modifier
  457. .padding(end = 6.dp)
  458. .size(15.dp)
  459. .clip(CircleShape)
  460. .paint(
  461. painter = painterResource(id = image),
  462. contentScale = ContentScale.FillBounds
  463. )
  464. )
  465. }
  466. AddText(
  467. text = "${serverDis?.city ?: ""}, ${serverDis?.country ?: ""}",
  468. size = 16.sp,
  469. color = colorResource(id = R.color.dark_blue_gray_text),
  470. isTablet()
  471. )
  472. }
  473. }
  474. when (isConnect) {
  475. App.CONNECTED -> {
  476. AddText(
  477. text = "Connected",
  478. size = 18.sp,
  479. // color = MaterialTheme.colorScheme.surfaceContainerHigh,
  480. color = colorResource(id = R.color.light_blue_2),
  481. style = MaterialTheme.typography.customTypography.displaySmall.copy(
  482. fontSize = 18.sp
  483. )
  484. )
  485. }
  486. App.DISCONNECTED -> {
  487. AddText(
  488. text = "Disconnected",
  489. size = 18.sp,
  490. // color = MaterialTheme.colorScheme.surfaceTint,
  491. color = colorResource(id = R.color.maroon_text),
  492. style = MaterialTheme.typography.customTypography.displaySmall.copy(
  493. fontSize = 18.sp
  494. )
  495. )
  496. }
  497. App.CONNECTING -> {
  498. AddText(
  499. text = "Connecting...",
  500. size = 18.sp,
  501. // color = MaterialTheme.colorScheme.surfaceTint,
  502. color = colorResource(id = R.color.maroon_text),
  503. style = MaterialTheme.typography.customTypography.displaySmall.copy(
  504. fontSize = 18.sp
  505. )
  506. )
  507. }
  508. }
  509. }
  510. }
  511. Box(
  512. modifier = Modifier
  513. .constrainAs(secondComposable) {
  514. top.linkTo(guideline)
  515. bottom.linkTo(firstComposable.bottom)
  516. start.linkTo(parent.start)
  517. end.linkTo(parent.end)
  518. width = Dimension.value(150.dp)
  519. height = Dimension.value(150.dp)
  520. }
  521. .background(Color.Transparent)
  522. ) {
  523. val color = if (isButtonFocused && isConnect == App.CONNECTED) colorResource(id = R.color.dark_blue_gray_text)
  524. else if (isButtonFocused) colorResource(id = R.color.maroon_text)
  525. else colorResource(id = R.color.transparent)
  526. IconButton(
  527. onClick = {
  528. // Toast.makeText(
  529. // context, "Connect onClick{}", Toast.LENGTH_SHORT
  530. // ).show()
  531. // val connectedServer = basePreferenceHelper.getConnectedServer()
  532. // val serverObject = basePreferenceHelper.getServerObject()
  533. // Log.d(
  534. // "test_conn_ser_obj",
  535. // "cs = ${connectedServer?.server_name} so = ${serverObject?.server_name}"
  536. // )
  537. // Log.d("isConnect_State", "onClick{} -> $isConnect")
  538. // Log.d("isConnect_State_vpn", "onClick{} -> $isConnect")
  539. // prefHelper.getProduct()?.identifier.let {
  540. // val identifier = it
  541. //
  542. // if (identifier == AppEnum.FREE.key) {
  543. // Log.d("isConnect_State", "identifier -> $identifier")
  544. // Screen.Subscription.isTrue = true
  545. // navHostController.navigate(
  546. // Screen.Subscription.route
  547. // )
  548. //
  549. // } else {
  550. //
  551. // prefHelper.getServerObject()?.let {
  552. // prefHelper.setConnectedServer(it)
  553. // }
  554. // Log.d("isConnect_State", "identifier -> $identifier")
  555. // if (isConnect == App.CONNECTED || isConnect == App.CONNECTING) {
  556. // Log.d("isConnect_State_vpn", "stopVPN")
  557. // vpnConnectionsUtil.stopVpn()
  558. // homeViewModel.getIp()
  559. // } else {
  560. // Log.d("isConnect_State_vpn", "startVPN")
  561. //
  562. // if (basePreferenceHelper.getServerObject() != null) {
  563. // vpnConnectionsUtil.startVpn()
  564. // } else {
  565. // toChangeServer.value = false
  566. // navHostController.navigate(
  567. // Screen.ServerList.route
  568. // )
  569. // Screen.ServerList.isTrue = true
  570. // Log.d("button_click_change", "Pressed")
  571. // }
  572. // }
  573. //
  574. //
  575. // val widgetIntent = Intent(context, SimpleAppWidget::class.java)
  576. // widgetIntent.action = SimpleAppWidget.ACTION_CHANGE_SERVER
  577. // context.sendBroadcast(widgetIntent)
  578. // }
  579. // }
  580. },
  581. modifier = Modifier
  582. .padding(bottom = 0.dp)
  583. .size(150.dp)
  584. .onKeyEvent {
  585. when (it.key) {
  586. Key.DirectionDown -> {
  587. Log.d("test_settings_keys", "DirectionDown")
  588. // Toast
  589. // .makeText(
  590. // context, "DirectionDown", Toast.LENGTH_SHORT
  591. // )
  592. // .show()
  593. if (it.type == KeyEventType.KeyDown) {
  594. // Toast
  595. // .makeText(
  596. // context, "KeyDown", Toast.LENGTH_SHORT
  597. // )
  598. // .show()
  599. focusRequester2.requestFocus()
  600. }
  601. true
  602. }
  603. else -> {
  604. true
  605. }
  606. }
  607. }
  608. .focusRequester(focusRequester1)
  609. .background(Color.Transparent)
  610. .onFocusChanged {
  611. isButtonFocused = it.isFocused
  612. }
  613. .clickable {
  614. if (isConnect == App.DISCONNECTED) homeViewModel.setConnectState(App.CONNECTED)
  615. else if (isConnect == App.CONNECTED) homeViewModel.setConnectState(App.DISCONNECTED)
  616. }
  617. .focusable()
  618. .border(
  619. BorderStroke(
  620. 2.dp, color
  621. ), shape = CircleShape
  622. ),
  623. )
  624. {
  625. if (isConnect == App.CONNECTED) {
  626. Image(
  627. // painter = if (isDarkTheme.value) painterResource(id = R.drawable.iv_connect_dark)
  628. // else painterResource(id = R.drawable.iv_connect),
  629. painter = painterResource(id = R.drawable.iv_connect),
  630. contentDescription = "Home Map",
  631. contentScale = ContentScale.FillBounds,
  632. modifier = Modifier.fillMaxSize()
  633. )
  634. } else {
  635. Image(
  636. // painter = if (isDarkTheme.value) painterResource(id = R.drawable.iv_disconnect_dark)
  637. // else painterResource(id = R.drawable.iv_disconnect),
  638. painter = painterResource(id = R.drawable.iv_disconnect),
  639. contentDescription = "Home Map",
  640. contentScale = ContentScale.FillBounds,
  641. modifier = Modifier.fillMaxSize()
  642. )
  643. }
  644. }
  645. }
  646. }
  647. // 2nd box
  648. Box(
  649. modifier = Modifier
  650. .background(colorResource(id = R.color.background_color_gray))
  651. .fillMaxSize()
  652. .weight(0.4f)
  653. // .background(Color.Transparent),
  654. ) {
  655. Column(
  656. modifier = Modifier.fillMaxSize(),
  657. verticalArrangement = Arrangement.Center
  658. ) {
  659. Box(
  660. modifier = Modifier
  661. .fillMaxWidth(fraction = 0.4f)
  662. .padding(horizontal = 0.dp)
  663. .padding(vertical = 2.dp)
  664. .height(90.dp)
  665. .border(
  666. border = BorderStroke(2.dp, colorResource(id = R.color.white)),
  667. shape = RoundedCornerShape(28.dp)
  668. )
  669. .background(
  670. shape = RoundedCornerShape(28.dp),
  671. color = colorResource(id = R.color.white)
  672. )
  673. .align(Alignment.CenterHorizontally),
  674. ) {
  675. AddRowSmartTV(
  676. navHostController,
  677. basePreferenceHelper,
  678. context,
  679. isTablet(),
  680. focusRequester2,
  681. homeViewModel
  682. )
  683. var smartServer = basePreferenceHelper.getSmartServerObject()
  684. val recommended = basePreferenceHelper.getRecommendedServerObject()
  685. val selectedSmartList = basePreferenceHelper.getSmartList()
  686. var isSmartButtonFocused by remember { mutableStateOf(false) }
  687. when(selectedSmartList) {
  688. smartConnect[0] -> {
  689. smartServer = basePreferenceHelper.getRecommendedServerObject()
  690. }
  691. smartConnect[1] -> {
  692. smartServer = basePreferenceHelper.getSmartServerObject() ?: recommended
  693. }
  694. smartConnect[2] -> {
  695. smartServer = basePreferenceHelper.getSmartServerObject() ?: recommended
  696. }
  697. else -> {}
  698. }
  699. val color = if (isSmartButtonFocused && isConnect == App.CONNECTED) colorResource(id = R.color.dark_blue_gray_text)
  700. else if (isSmartButtonFocused) colorResource(id = R.color.maroon_text)
  701. else colorResource(id = R.color.blue_text)
  702. Button(
  703. onClick = {
  704. // Toast.makeText(
  705. // context, "Smart onClick{}", Toast.LENGTH_SHORT
  706. // ).show()
  707. // Log.d("test_button", "onClick Smart Connect ${smartServer?.server_name}")
  708. // basePreferenceHelper.setSmartServerObject(smartServer)
  709. // if (isConnect == App.CONNECTED) {
  710. // Log.d("isConnect_State_vpn", "stopVPN")
  711. // val lastServer = basePreferenceHelper.getConnectedServer()
  712. // Log.d("test_conn_ser_obj", "smart => ${lastServer?.server_name} ${smartServer?.server_name}")
  713. //
  714. // if (lastServer?.id != smartServer?.id) {
  715. // isServerDialog.value = true
  716. // if (smartServer != null) {
  717. // serverObj.value = smartServer
  718. // }
  719. //// basePreferenceHelper.setConnectedServer(smartServer)
  720. //
  721. // }
  722. // else {
  723. // vpnConnectionsUtil.stopVpn()
  724. // }
  725. //
  726. //
  727. //// vpnConnectionsUtil.stopVpn()
  728. //// Handler().postDelayed(Runnable {
  729. //// vpnConnectionsUtil.startVpn()
  730. //// }, 500)
  731. //// homeViewModel.getIp()
  732. // }
  733. // else if (isConnect == App.CONNECTING) {
  734. // vpnConnectionsUtil.stopVpn()
  735. // }
  736. // else if (isConnect == App.DISCONNECTED) {
  737. // Log.d("isConnect_State_vpn", "startVPN")
  738. // basePreferenceHelper.setConnectedServer(smartServer)
  739. // if (smartServer != null) {
  740. //// serverListViewModel.setRecentlyConnectedServer(smartServer)
  741. // }
  742. // vpnConnectionsUtil.startVpn()
  743. // }
  744. },
  745. modifier = Modifier
  746. .padding(start = 14.dp, end = 14.dp, bottom = 6.dp, top = 12.dp)
  747. .align(Alignment.BottomCenter)
  748. .background(colorResource(id = R.color.transparent))
  749. .onFocusChanged {
  750. isSmartButtonFocused = it.isFocused
  751. }
  752. // .focusable()
  753. // .clickable {
  754. // Toast.makeText(
  755. // context, "Smart clickable{}", Toast.LENGTH_SHORT
  756. // ).show()
  757. // }
  758. .fillMaxWidth()
  759. .height(35.dp),
  760. shape = RoundedCornerShape(16.dp),
  761. colors = ButtonDefaults.buttonColors(
  762. contentColor = colorResource(id = R.color.white),
  763. containerColor = color,
  764. ),
  765. ) {
  766. Text(
  767. text = "Smart Connect",
  768. style = MaterialTheme.typography.customTypography.labelLarge.copy(
  769. fontSize = 16.sp, lineHeight = 0.sp
  770. ),
  771. modifier = Modifier.background(Color.Transparent)
  772. )
  773. }
  774. }
  775. /* Select Server Box*/
  776. // if (isConnect != App.CONNECTED) { }
  777. // Spacer(modifier = Modifier.weight(1f))
  778. var isLayoutFocused by remember { mutableStateOf(false) }
  779. val color = if (isLayoutFocused && isConnect == App.CONNECTED) colorResource(id = R.color.dark_blue_gray_text)
  780. else if (isLayoutFocused) colorResource(id = R.color.maroon_text)
  781. else colorResource(id = R.color.white)
  782. Box(
  783. modifier = Modifier
  784. .fillMaxWidth(fraction = 0.4f)
  785. .padding(horizontal = 0.dp, vertical = 2.dp)
  786. .padding(top = 0.dp)
  787. .height(50.dp)
  788. .onKeyEvent {
  789. if (it.type == KeyEventType.KeyDown && it.key == Key.DirectionDown) {
  790. // Toast
  791. // .makeText(
  792. // context, "KeyDown & DirectionDown", Toast.LENGTH_SHORT
  793. // )
  794. // .show()
  795. isFirstItemPressed.value = true
  796. true
  797. } else {
  798. false
  799. }
  800. }
  801. .onFocusChanged {
  802. isLayoutFocused = it.isFocused
  803. }
  804. .focusable()
  805. .clickable(
  806. indication = null,
  807. interactionSource = remember { MutableInteractionSource() }
  808. ) {
  809. // Toast
  810. // .makeText(context, "See All Pressed", Toast.LENGTH_SHORT)
  811. // .show()
  812. toChangeServer.value = false
  813. navHostController.navigate(
  814. ScreenTV.ServerListTV.route
  815. )
  816. }
  817. .border(
  818. border = BorderStroke(2.dp, color),
  819. shape = RoundedCornerShape(28.dp)
  820. )
  821. .background(
  822. shape = RoundedCornerShape(28.dp),
  823. // color = MaterialTheme.colorScheme.onBackground
  824. color = colorResource(id = R.color.white)
  825. )
  826. .align(Alignment.CenterHorizontally),
  827. contentAlignment = Alignment.CenterStart,
  828. ) {
  829. AddRowSelectServerTV(navHostController, isTablet())
  830. }
  831. }
  832. }
  833. }
  834. }
  835. @Composable
  836. fun BoxScope.AddRowSmartTV(
  837. navHostController: NavHostController,
  838. basePreferenceHelper: BasePreferenceHelper,
  839. context: Context,
  840. isTablet: Boolean,
  841. focusRequester2: FocusRequester,
  842. homeViewModel: HomeViewModel
  843. ) {
  844. val smart = basePreferenceHelper.getSmartServerObject()
  845. val recommended = basePreferenceHelper.getRecommendedServerObject()
  846. val recently = basePreferenceHelper.getConnectedServer()
  847. val anySpecific = basePreferenceHelper.getSmartServerObject()
  848. val ipInfo = basePreferenceHelper.getIpinfo()
  849. val selectedSmartList = basePreferenceHelper.getSmartList()
  850. var selectedServer = basePreferenceHelper.getRecommendedServerObject()
  851. var selectedSmartServer = basePreferenceHelper.getSmartServerObject()
  852. var isButtonFocused by remember { mutableStateOf(false) }
  853. Log.d("smartLocationList", "Home:: server = ${selectedServer?.server_name}")
  854. var icon = Utils.getDrawable(context, selectedServer?.iso)
  855. when(selectedSmartList) {
  856. smartConnect[0] -> {
  857. icon = Utils.getDrawable(context, recommended?.iso)
  858. selectedServer = recommended
  859. selectedSmartServer = recommended
  860. }
  861. smartConnect[1] -> {
  862. icon = Utils.getDrawable(context, recently?.iso ?: recommended?.iso)
  863. selectedServer = recently ?: recommended
  864. selectedSmartServer = recently
  865. }
  866. smartConnect[2] -> {
  867. icon = Utils.getDrawable(context, anySpecific?.iso ?: recommended?.iso)
  868. selectedServer = anySpecific ?: recommended
  869. selectedSmartServer = anySpecific
  870. }
  871. else -> {}
  872. }
  873. Row(
  874. modifier = Modifier
  875. .fillMaxWidth()
  876. .padding(horizontal = 15.dp, vertical = 5.dp)
  877. .background(Color.Transparent),
  878. horizontalArrangement = Arrangement.Start,
  879. verticalAlignment = Alignment.CenterVertically
  880. ) {
  881. Surface(
  882. modifier = Modifier.padding(start = 0.dp),
  883. color = Color.Transparent
  884. ) {
  885. if (icon != 0) {
  886. Icon(
  887. painter = painterResource(id = icon),
  888. contentDescription = "Country Logo",
  889. tint = Color.Unspecified,
  890. modifier = Modifier
  891. .padding(start = 0.dp)
  892. .size(30.dp)
  893. .weight(1f)
  894. .clip(CircleShape)
  895. .border(1.dp, colorResource(id = R.color.gray_opac_04), CircleShape)
  896. .paint(
  897. painter = painterResource(id = icon),
  898. contentScale = ContentScale.FillBounds
  899. )
  900. )
  901. }
  902. }
  903. Column(
  904. modifier = Modifier
  905. .padding(start = 12.dp)
  906. ) {
  907. ColumnText(
  908. text = selectedSmartList,
  909. // color = MaterialTheme.colorScheme.surfaceContainerLow,
  910. color = colorResource(id = R.color.blue_text),
  911. size = 12.sp,
  912. style = MaterialTheme.typography.customTypography.headlineSmall.copy(
  913. fontSize = 16.sp
  914. )
  915. )
  916. ColumnText(
  917. text = "${selectedServer?.server_name}",
  918. // color = MaterialTheme.colorScheme.primary,
  919. color = colorResource(id = R.color.dark_blue_gray_text),
  920. size = 16.sp,
  921. style = MaterialTheme.typography.labelMedium.copy(
  922. fontSize = 16.sp
  923. )
  924. )
  925. }
  926. Spacer(modifier = Modifier.weight(1F))
  927. Surface(
  928. modifier = Modifier
  929. .padding(start = 15.dp),
  930. color = Color.Transparent
  931. ) {
  932. var isConnect: Int? = homeViewModel.isConnect.observeAsState().value
  933. isConnect = basePreferenceHelper.getConnectState()
  934. val color = if (isButtonFocused && isConnect == App.CONNECTED) colorResource(id = R.color.dark_blue_gray_text)
  935. else if (isButtonFocused) colorResource(id = R.color.maroon_text)
  936. else colorResource(id = R.color.blue_text)
  937. ClickableText(
  938. modifier = Modifier
  939. .onKeyEvent {
  940. when (it.key) {
  941. Key.DirectionLeft -> {
  942. // Toast.makeText(
  943. // context, "DirectionLeft Change", Toast.LENGTH_SHORT
  944. // ).show()
  945. true
  946. }
  947. else -> {
  948. false
  949. }
  950. }
  951. }
  952. .focusRequester(focusRequester2)
  953. .onFocusChanged {
  954. isButtonFocused = it.isFocused
  955. }
  956. .clickable {
  957. toChangeServer.value = true
  958. navHostController.navigate(
  959. ScreenTV.ServerListTV.route
  960. )
  961. }
  962. .focusable(),
  963. text = AnnotatedString("Change"),
  964. style = MaterialTheme.typography.customTypography.headlineMedium.copy(
  965. // MaterialTheme.colorScheme.surfaceContainerLow,
  966. color = color,
  967. fontSize = 18.sp
  968. ),
  969. onClick = {},
  970. )
  971. }
  972. }
  973. }
  974. @Composable
  975. fun BoxScope.AddRowSelectServerTV(navHostController: NavHostController, isTablet: Boolean) {
  976. val context = LocalContext.current
  977. Row(
  978. modifier = Modifier
  979. .fillMaxWidth()
  980. .padding(horizontal = 15.dp)
  981. .background(Color.Transparent)
  982. // .pointerInput(Unit) {
  983. // detectTapGestures {
  984. // toChangeServer.value = false
  985. // navHostController.navigate(
  986. // Screen.ServerList.route
  987. // )
  988. // Screen.ServerList.isTrue = true
  989. // Log.d("button_click_change", "Pressed")
  990. // }
  991. // }
  992. ,
  993. horizontalArrangement = Arrangement.Start,
  994. verticalAlignment = Alignment.CenterVertically
  995. ) {
  996. Surface(
  997. modifier = Modifier.padding(start = 0.dp),
  998. color = Color.Transparent
  999. ) {
  1000. Image(
  1001. painter = painterResource(id = R.drawable.worldmap3x),
  1002. contentDescription = "World",
  1003. modifier = Modifier
  1004. .padding(start = 0.dp)
  1005. .size(30.dp)
  1006. .weight(1f)
  1007. )
  1008. }
  1009. Surface(
  1010. modifier = Modifier.padding(start = 0.dp),
  1011. color = Color.Transparent
  1012. ) {
  1013. Text(text = "See All Locations",
  1014. style = MaterialTheme.typography.labelMedium.copy(
  1015. fontSize = if (isTablet()) 20.sp else 16.sp
  1016. ),
  1017. // color = MaterialTheme.colorScheme.primary,
  1018. color = colorResource(id = R.color.dark_blue_gray_text),
  1019. maxLines = 2,
  1020. modifier = Modifier
  1021. .padding(start = 12.dp, end = 0.dp)
  1022. .weight(1f)
  1023. )
  1024. }
  1025. Spacer(modifier = Modifier.weight(1F))
  1026. Surface(
  1027. modifier = Modifier.padding(start = 15.dp),
  1028. color = Color.Transparent
  1029. ) {
  1030. Image(
  1031. painter = painterResource(id = R.drawable.frontarrow3x),
  1032. contentDescription = "Front_Arrow",
  1033. colorFilter = ColorFilter.tint(colorResource(id = R.color.dark_blue_gray_text)),
  1034. modifier = Modifier
  1035. .padding(start = 0.dp, end = 5.dp)
  1036. .size(10.dp, 18.dp)
  1037. .weight(1f)
  1038. )
  1039. }
  1040. }
  1041. }
  1042. @Composable
  1043. fun ColumnScope.AddText(
  1044. text: String,
  1045. size: TextUnit,
  1046. color: Color,
  1047. style: TextStyle
  1048. ) {
  1049. Text(
  1050. text = text,
  1051. style = style,
  1052. color = color,
  1053. modifier = Modifier.padding(top = 5.dp)
  1054. )
  1055. }
  1056. @Composable
  1057. fun ColumnScope.ColumnText(
  1058. text: String,
  1059. color: Color,
  1060. size: TextUnit,
  1061. style: TextStyle
  1062. ) {
  1063. Surface(
  1064. modifier = Modifier.padding(start = 0.dp),
  1065. color = Color.Transparent
  1066. ) {
  1067. Text(text = text,
  1068. style = style,
  1069. color = color,
  1070. maxLines = 1,
  1071. modifier = Modifier
  1072. .padding(start = 0.dp, end = 0.dp)
  1073. .weight(1f)
  1074. )
  1075. }
  1076. }
  1077. @Composable
  1078. fun RowScope.AddText(
  1079. text: String,
  1080. size: TextUnit,
  1081. color: Color,
  1082. isTablet: Boolean
  1083. ) {
  1084. Text(
  1085. text = text,
  1086. style = MaterialTheme.typography.labelMedium.copy(
  1087. fontSize = 18.sp
  1088. ),
  1089. color = color,
  1090. modifier = Modifier.padding(top = 0.dp)
  1091. )
  1092. }
  1093. @Composable
  1094. fun OnLifecycleEvent(onEvent: (
  1095. owner: LifecycleOwner,
  1096. event: Lifecycle.Event
  1097. ) -> Unit) {
  1098. val eventHandler = rememberUpdatedState(onEvent)
  1099. val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
  1100. DisposableEffect(lifecycleOwner.value) {
  1101. val lifecycle = lifecycleOwner.value.lifecycle
  1102. val observer = LifecycleEventObserver { owner, event ->
  1103. eventHandler.value(owner, event)
  1104. }
  1105. lifecycle.addObserver(observer)
  1106. onDispose {
  1107. lifecycle.removeObserver(observer)
  1108. }
  1109. }
  1110. }
  1111. private fun getEnableProtocols(protocol_name: String, prefHelper: BasePreferenceHelper): Boolean {
  1112. prefHelper.getEnabledProtocols().let {
  1113. if (it.contains(protocol_name)) {
  1114. return true
  1115. }
  1116. }
  1117. return false
  1118. }
  1119. @Composable
  1120. fun pinkBackgroundTV(): Painter {
  1121. return if (isDarkTheme.value) painterResource(id = R.drawable.darkpinkbackground)
  1122. else painterResource(id = R.drawable.pinkbackground3x)
  1123. }
  1124. @Composable
  1125. fun blueBackgroundTV(): Painter {
  1126. return if (isDarkTheme.value) painterResource(id = R.drawable.darkbluebackground)
  1127. else painterResource(id = R.drawable.bluebackground3x)
  1128. }