HomeScreenTV.kt 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  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.dark_blue_gray_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. if (isConnect == App.DISCONNECTED) homeViewModel.setConnectState(App.CONNECTED)
  432. else if (isConnect == App.CONNECTED) homeViewModel.setConnectState(App.DISCONNECTED)
  433. }
  434. .focusable()
  435. .border(
  436. BorderStroke(
  437. 2.dp, color
  438. ), shape = CircleShape
  439. ),
  440. )
  441. {
  442. if (isConnect == App.CONNECTED) {
  443. Image(
  444. // painter = if (isDarkTheme.value) painterResource(id = R.drawable.iv_connect_dark)
  445. // else painterResource(id = R.drawable.iv_connect),
  446. painter = painterResource(id = R.drawable.iv_connect),
  447. contentDescription = "Home Map",
  448. contentScale = ContentScale.FillBounds,
  449. modifier = Modifier.fillMaxSize()
  450. )
  451. } else {
  452. Image(
  453. // painter = if (isDarkTheme.value) painterResource(id = R.drawable.iv_disconnect_dark)
  454. // else painterResource(id = R.drawable.iv_disconnect),
  455. painter = painterResource(id = R.drawable.iv_disconnect),
  456. contentDescription = "Home Map",
  457. contentScale = ContentScale.FillBounds,
  458. modifier = Modifier.fillMaxSize()
  459. )
  460. }
  461. }
  462. }
  463. }
  464. // 2nd box
  465. Box(
  466. modifier = Modifier
  467. .background(colorResource(id = R.color.background_color_gray))
  468. .fillMaxSize()
  469. .weight(0.35f)
  470. // .background(Color.Transparent),
  471. ) {
  472. Column(
  473. modifier = Modifier.fillMaxSize(),
  474. verticalArrangement = Arrangement.Top
  475. ) {
  476. Box(
  477. modifier = Modifier
  478. .fillMaxWidth(fraction = if (isTablet()) 0.5f else 1f)
  479. .padding(horizontal = 20.dp)
  480. .padding(vertical = 2.dp)
  481. .height(100.dp)
  482. .border(
  483. border = BorderStroke(2.dp, colorResource(id = R.color.white)),
  484. shape = RoundedCornerShape(28.dp)
  485. )
  486. .background(
  487. shape = RoundedCornerShape(28.dp),
  488. color = colorResource(id = R.color.white)
  489. )
  490. .align(Alignment.CenterHorizontally),
  491. ) {
  492. AddRowSmartTV(
  493. navHostController,
  494. basePreferenceHelper,
  495. context,
  496. isTablet(),
  497. focusRequester2,
  498. homeViewModel
  499. )
  500. var smartServer = basePreferenceHelper.getSmartServerObject()
  501. val recommended = basePreferenceHelper.getRecommendedServerObject()
  502. val selectedSmartList = basePreferenceHelper.getSmartList()
  503. var isSmartButtonFocused by remember { mutableStateOf(false) }
  504. when(selectedSmartList) {
  505. smartConnect[0] -> {
  506. smartServer = basePreferenceHelper.getRecommendedServerObject()
  507. }
  508. smartConnect[1] -> {
  509. smartServer = basePreferenceHelper.getSmartServerObject() ?: recommended
  510. }
  511. smartConnect[2] -> {
  512. smartServer = basePreferenceHelper.getSmartServerObject() ?: recommended
  513. }
  514. else -> {}
  515. }
  516. val color = if (isSmartButtonFocused && isConnect == App.CONNECTED) colorResource(id = R.color.dark_blue_gray_text)
  517. else if (isSmartButtonFocused) colorResource(id = R.color.maroon_text)
  518. else colorResource(id = R.color.blue_text)
  519. Button(
  520. onClick = {
  521. // Toast.makeText(
  522. // context, "Smart onClick{}", Toast.LENGTH_SHORT
  523. // ).show()
  524. // Log.d("test_button", "onClick Smart Connect ${smartServer?.server_name}")
  525. // basePreferenceHelper.setSmartServerObject(smartServer)
  526. // if (isConnect == App.CONNECTED) {
  527. // Log.d("isConnect_State_vpn", "stopVPN")
  528. // val lastServer = basePreferenceHelper.getConnectedServer()
  529. // Log.d("test_conn_ser_obj", "smart => ${lastServer?.server_name} ${smartServer?.server_name}")
  530. //
  531. // if (lastServer?.id != smartServer?.id) {
  532. // isServerDialog.value = true
  533. // if (smartServer != null) {
  534. // serverObj.value = smartServer
  535. // }
  536. //// basePreferenceHelper.setConnectedServer(smartServer)
  537. //
  538. // }
  539. // else {
  540. // vpnConnectionsUtil.stopVpn()
  541. // }
  542. //
  543. //
  544. //// vpnConnectionsUtil.stopVpn()
  545. //// Handler().postDelayed(Runnable {
  546. //// vpnConnectionsUtil.startVpn()
  547. //// }, 500)
  548. //// homeViewModel.getIp()
  549. // }
  550. // else if (isConnect == App.CONNECTING) {
  551. // vpnConnectionsUtil.stopVpn()
  552. // }
  553. // else if (isConnect == App.DISCONNECTED) {
  554. // Log.d("isConnect_State_vpn", "startVPN")
  555. // basePreferenceHelper.setConnectedServer(smartServer)
  556. // if (smartServer != null) {
  557. //// serverListViewModel.setRecentlyConnectedServer(smartServer)
  558. // }
  559. // vpnConnectionsUtil.startVpn()
  560. // }
  561. },
  562. modifier = Modifier
  563. .padding(start = 14.dp, end = 14.dp, bottom = 8.dp, top = 16.dp)
  564. .align(Alignment.BottomCenter)
  565. .background(colorResource(id = R.color.transparent))
  566. .onFocusChanged {
  567. isSmartButtonFocused = it.isFocused
  568. }
  569. // .focusable()
  570. // .clickable {
  571. // Toast.makeText(
  572. // context, "Smart clickable{}", Toast.LENGTH_SHORT
  573. // ).show()
  574. // }
  575. .fillMaxWidth()
  576. .height(40.dp),
  577. shape = RoundedCornerShape(16.dp),
  578. colors = ButtonDefaults.buttonColors(
  579. contentColor = colorResource(id = R.color.white),
  580. containerColor = color,
  581. ),
  582. ) {
  583. Text(
  584. text = "Smart Connect",
  585. style = MaterialTheme.typography.customTypography.labelLarge.copy(
  586. fontSize = if (isTablet()) 21.sp else 18.sp
  587. ),
  588. modifier = Modifier.background(Color.Transparent)
  589. )
  590. }
  591. }
  592. /* Select Server Box*/
  593. // if (isConnect != App.CONNECTED) { }
  594. // Spacer(modifier = Modifier.weight(1f))
  595. var isLayoutFocused by remember { mutableStateOf(false) }
  596. val color = if (isLayoutFocused && isConnect == App.CONNECTED) colorResource(id = R.color.dark_blue_gray_text)
  597. else if (isLayoutFocused) colorResource(id = R.color.maroon_text)
  598. else colorResource(id = R.color.white)
  599. Box(
  600. modifier = Modifier
  601. .fillMaxWidth(fraction = if (isTablet()) 0.5f else 1f)
  602. .padding(horizontal = 20.dp, vertical = 2.dp)
  603. .padding(top = 0.dp)
  604. .height(55.dp)
  605. .onKeyEvent {
  606. if (it.type == KeyEventType.KeyDown && it.key == Key.DirectionDown) {
  607. // Toast
  608. // .makeText(
  609. // context, "KeyDown & DirectionDown", Toast.LENGTH_SHORT
  610. // )
  611. // .show()
  612. isFirstItemPressed.value = true
  613. true
  614. } else {
  615. false
  616. }
  617. }
  618. .onFocusChanged {
  619. isLayoutFocused = it.isFocused
  620. }
  621. .focusable()
  622. .clickable(
  623. indication = null,
  624. interactionSource = remember { MutableInteractionSource() }
  625. ) {
  626. // Toast
  627. // .makeText(context, "See All Pressed", Toast.LENGTH_SHORT)
  628. // .show()
  629. navHostController.navigate(
  630. ScreenTV.ServerListTV.route
  631. )
  632. }
  633. .border(
  634. border = BorderStroke(2.dp, color),
  635. shape = RoundedCornerShape(28.dp)
  636. )
  637. .background(
  638. shape = RoundedCornerShape(28.dp),
  639. // color = MaterialTheme.colorScheme.onBackground
  640. color = colorResource(id = R.color.white)
  641. )
  642. .align(Alignment.CenterHorizontally),
  643. contentAlignment = Alignment.CenterStart,
  644. ) {
  645. AddRowSelectServerTV(navHostController, isTablet())
  646. }
  647. }
  648. }
  649. }
  650. }
  651. @Composable
  652. fun BoxScope.AddRowSmartTV(
  653. navHostController: NavHostController,
  654. basePreferenceHelper: BasePreferenceHelper,
  655. context: Context,
  656. isTablet: Boolean,
  657. focusRequester2: FocusRequester,
  658. homeViewModel: HomeViewModel
  659. ) {
  660. val smart = basePreferenceHelper.getSmartServerObject()
  661. val recommended = basePreferenceHelper.getRecommendedServerObject()
  662. val recently = basePreferenceHelper.getConnectedServer()
  663. val anySpecific = basePreferenceHelper.getSmartServerObject()
  664. val ipInfo = basePreferenceHelper.getIpinfo()
  665. val selectedSmartList = basePreferenceHelper.getSmartList()
  666. var selectedServer = basePreferenceHelper.getRecommendedServerObject()
  667. var selectedSmartServer = basePreferenceHelper.getSmartServerObject()
  668. var isButtonFocused by remember { mutableStateOf(false) }
  669. Log.d("smartLocationList", "Home:: server = ${selectedServer?.server_name}")
  670. var icon = Utils.getDrawable(context, selectedServer?.iso)
  671. when(selectedSmartList) {
  672. smartConnect[0] -> {
  673. icon = Utils.getDrawable(context, recommended?.iso)
  674. selectedServer = recommended
  675. selectedSmartServer = recommended
  676. }
  677. smartConnect[1] -> {
  678. icon = Utils.getDrawable(context, recently?.iso ?: recommended?.iso)
  679. selectedServer = recently ?: recommended
  680. selectedSmartServer = recently
  681. }
  682. smartConnect[2] -> {
  683. icon = Utils.getDrawable(context, anySpecific?.iso ?: recommended?.iso)
  684. selectedServer = anySpecific ?: recommended
  685. selectedSmartServer = anySpecific
  686. }
  687. else -> {}
  688. }
  689. Row(
  690. modifier = Modifier
  691. .fillMaxWidth()
  692. .padding(horizontal = 15.dp, vertical = 5.dp)
  693. .background(Color.Transparent),
  694. horizontalArrangement = Arrangement.Start,
  695. verticalAlignment = Alignment.CenterVertically
  696. ) {
  697. Surface(
  698. modifier = Modifier.padding(start = 0.dp),
  699. color = Color.Transparent
  700. ) {
  701. if (icon != 0) {
  702. Icon(
  703. painter = painterResource(id = icon),
  704. contentDescription = "Country Logo",
  705. tint = Color.Unspecified,
  706. modifier = Modifier
  707. .padding(start = 0.dp)
  708. .size(40.dp)
  709. .weight(1f)
  710. .clip(CircleShape)
  711. .border(1.dp, colorResource(id = R.color.gray_opac_04), CircleShape)
  712. .paint(
  713. painter = painterResource(id = icon),
  714. contentScale = ContentScale.FillBounds
  715. )
  716. )
  717. }
  718. }
  719. Column(
  720. modifier = Modifier
  721. .padding(start = 12.dp)
  722. ) {
  723. ColumnText(
  724. text = selectedSmartList,
  725. // color = MaterialTheme.colorScheme.surfaceContainerLow,
  726. color = colorResource(id = R.color.blue_text),
  727. size = 12.sp,
  728. style = MaterialTheme.typography.customTypography.headlineSmall.copy(
  729. fontSize = if (isTablet()) 16.sp else 12.sp
  730. )
  731. )
  732. ColumnText(
  733. text = "${selectedServer?.server_name}",
  734. // color = MaterialTheme.colorScheme.primary,
  735. color = colorResource(id = R.color.dark_blue_gray_text),
  736. size = 16.sp,
  737. style = MaterialTheme.typography.labelMedium.copy(
  738. fontSize = if (isTablet()) 20.sp else 16.sp
  739. )
  740. )
  741. }
  742. Spacer(modifier = Modifier.weight(1F))
  743. Surface(
  744. modifier = Modifier
  745. .padding(start = 15.dp),
  746. color = Color.Transparent
  747. ) {
  748. var isConnect: Int? = homeViewModel.isConnect.observeAsState().value
  749. isConnect = basePreferenceHelper.getConnectState()
  750. val color = if (isButtonFocused && isConnect == App.CONNECTED) colorResource(id = R.color.dark_blue_gray_text)
  751. else if (isButtonFocused) colorResource(id = R.color.maroon_text)
  752. else colorResource(id = R.color.blue_text)
  753. ClickableText(
  754. modifier = Modifier
  755. .onKeyEvent {
  756. when (it.key) {
  757. Key.DirectionLeft -> {
  758. // Toast.makeText(
  759. // context, "DirectionLeft Change", Toast.LENGTH_SHORT
  760. // ).show()
  761. true
  762. }
  763. else -> {
  764. false
  765. }
  766. }
  767. }
  768. .focusRequester(focusRequester2)
  769. .onFocusChanged {
  770. isButtonFocused = it.isFocused
  771. }
  772. .clickable {
  773. navHostController.navigate(
  774. ScreenTV.ServerListTV.route
  775. )
  776. }
  777. .focusable()
  778. ,
  779. text = AnnotatedString("Change"),
  780. style = MaterialTheme.typography.customTypography.headlineMedium.copy(
  781. // MaterialTheme.colorScheme.surfaceContainerLow,
  782. color = color,
  783. fontSize = if (isTablet()) 20.sp else 14.sp
  784. ),
  785. onClick = {},
  786. )
  787. }
  788. }
  789. }
  790. @Composable
  791. fun BoxScope.AddRowSelectServerTV(navHostController: NavHostController, isTablet: Boolean) {
  792. val context = LocalContext.current
  793. Row(
  794. modifier = Modifier
  795. .fillMaxWidth()
  796. .padding(horizontal = 15.dp)
  797. .background(Color.Transparent)
  798. // .pointerInput(Unit) {
  799. // detectTapGestures {
  800. // toChangeServer.value = false
  801. // navHostController.navigate(
  802. // Screen.ServerList.route
  803. // )
  804. // Screen.ServerList.isTrue = true
  805. // Log.d("button_click_change", "Pressed")
  806. // }
  807. // }
  808. ,
  809. horizontalArrangement = Arrangement.Start,
  810. verticalAlignment = Alignment.CenterVertically
  811. ) {
  812. Surface(
  813. modifier = Modifier.padding(start = 0.dp),
  814. color = Color.Transparent
  815. ) {
  816. Image(
  817. painter = painterResource(id = R.drawable.worldmap3x),
  818. contentDescription = "World",
  819. modifier = Modifier
  820. .padding(start = 0.dp)
  821. .size(30.dp)
  822. .weight(1f)
  823. )
  824. }
  825. Surface(
  826. modifier = Modifier.padding(start = 0.dp),
  827. color = Color.Transparent
  828. ) {
  829. Text(text = "See All Locations",
  830. style = MaterialTheme.typography.labelMedium.copy(
  831. fontSize = if (isTablet()) 20.sp else 16.sp
  832. ),
  833. // color = MaterialTheme.colorScheme.primary,
  834. color = colorResource(id = R.color.dark_blue_gray_text),
  835. maxLines = 2,
  836. modifier = Modifier
  837. .padding(start = 12.dp, end = 0.dp)
  838. .weight(1f)
  839. )
  840. }
  841. Spacer(modifier = Modifier.weight(1F))
  842. Surface(
  843. modifier = Modifier.padding(start = 15.dp),
  844. color = Color.Transparent
  845. ) {
  846. Image(
  847. painter = painterResource(id = R.drawable.frontarrow3x),
  848. contentDescription = "Front_Arrow",
  849. colorFilter = ColorFilter.tint(colorResource(id = R.color.dark_blue_gray_text)),
  850. modifier = Modifier
  851. .padding(start = 0.dp, end = 5.dp)
  852. .size(10.dp, 18.dp)
  853. .weight(1f)
  854. )
  855. }
  856. }
  857. }
  858. @Composable
  859. fun ColumnScope.AddText(
  860. text: String,
  861. size: TextUnit,
  862. color: Color,
  863. style: TextStyle
  864. ) {
  865. Text(
  866. text = text,
  867. style = style,
  868. color = color,
  869. modifier = Modifier.padding(bottom = if (isTablet()) 15.dp else 0.dp)
  870. )
  871. }
  872. @Composable
  873. fun ColumnScope.ColumnText(
  874. text: String,
  875. color: Color,
  876. size: TextUnit,
  877. style: TextStyle
  878. ) {
  879. Surface(
  880. modifier = Modifier.padding(start = 0.dp),
  881. color = Color.Transparent
  882. ) {
  883. Text(text = text,
  884. style = style,
  885. color = color,
  886. maxLines = 1,
  887. modifier = Modifier
  888. .padding(start = 0.dp, end = 0.dp)
  889. .weight(1f)
  890. )
  891. }
  892. }
  893. @Composable
  894. fun RowScope.AddText(
  895. text: String,
  896. size: TextUnit,
  897. color: Color,
  898. isTablet: Boolean
  899. ) {
  900. Text(
  901. text = text,
  902. style = MaterialTheme.typography.labelMedium.copy(
  903. fontSize = if (isTablet()) 22.sp else 16.sp
  904. ),
  905. color = color,
  906. modifier = Modifier.padding(bottom = if (isTablet()) 15.dp else 0.dp)
  907. )
  908. }
  909. @Composable
  910. fun OnLifecycleEvent(onEvent: (
  911. owner: LifecycleOwner,
  912. event: Lifecycle.Event
  913. ) -> Unit) {
  914. val eventHandler = rememberUpdatedState(onEvent)
  915. val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
  916. DisposableEffect(lifecycleOwner.value) {
  917. val lifecycle = lifecycleOwner.value.lifecycle
  918. val observer = LifecycleEventObserver { owner, event ->
  919. eventHandler.value(owner, event)
  920. }
  921. lifecycle.addObserver(observer)
  922. onDispose {
  923. lifecycle.removeObserver(observer)
  924. }
  925. }
  926. }
  927. @Composable
  928. fun pinkBackgroundTV(): Painter {
  929. return if (isDarkTheme.value) painterResource(id = R.drawable.darkpinkbackground)
  930. else painterResource(id = R.drawable.pinkbackground3x)
  931. }
  932. @Composable
  933. fun blueBackgroundTV(): Painter {
  934. return if (isDarkTheme.value) painterResource(id = R.drawable.darkbluebackground)
  935. else painterResource(id = R.drawable.bluebackground3x)
  936. }