HomeScreenTV.kt 41 KB

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