HomeScreenTV.kt 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849
  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.os.Handler
  6. import android.util.Log
  7. import android.widget.Toast
  8. import androidx.activity.ComponentActivity
  9. import androidx.compose.animation.animateColorAsState
  10. import androidx.compose.foundation.BorderStroke
  11. import androidx.compose.foundation.Image
  12. import androidx.compose.foundation.background
  13. import androidx.compose.foundation.border
  14. import androidx.compose.foundation.clickable
  15. import androidx.compose.foundation.focusable
  16. import androidx.compose.foundation.interaction.MutableInteractionSource
  17. import androidx.compose.foundation.layout.Arrangement
  18. import androidx.compose.foundation.layout.Box
  19. import androidx.compose.foundation.layout.BoxScope
  20. import androidx.compose.foundation.layout.Column
  21. import androidx.compose.foundation.layout.ColumnScope
  22. import androidx.compose.foundation.layout.Row
  23. import androidx.compose.foundation.layout.RowScope
  24. import androidx.compose.foundation.layout.Spacer
  25. import androidx.compose.foundation.layout.fillMaxHeight
  26. import androidx.compose.foundation.layout.fillMaxSize
  27. import androidx.compose.foundation.layout.fillMaxWidth
  28. import androidx.compose.foundation.layout.height
  29. import androidx.compose.foundation.layout.padding
  30. import androidx.compose.foundation.layout.size
  31. import androidx.compose.foundation.layout.wrapContentHeight
  32. import androidx.compose.foundation.shape.CircleShape
  33. import androidx.compose.foundation.shape.RoundedCornerShape
  34. import androidx.compose.foundation.text.ClickableText
  35. import androidx.compose.material.icons.Icons
  36. import androidx.compose.material.icons.outlined.ThumbDown
  37. import androidx.compose.material.icons.outlined.ThumbUp
  38. import androidx.compose.material.ripple.rememberRipple
  39. import androidx.compose.material3.AlertDialog
  40. import androidx.compose.material3.Button
  41. import androidx.compose.material3.ButtonDefaults
  42. import androidx.compose.material3.ExperimentalMaterial3Api
  43. import androidx.compose.material3.Icon
  44. import androidx.compose.material3.IconButton
  45. import androidx.compose.material3.MaterialTheme
  46. import androidx.compose.material3.Surface
  47. import androidx.compose.material3.Text
  48. import androidx.compose.runtime.Composable
  49. import androidx.compose.runtime.DisposableEffect
  50. import androidx.compose.runtime.LaunchedEffect
  51. import androidx.compose.runtime.MutableState
  52. import androidx.compose.runtime.getValue
  53. import androidx.compose.runtime.livedata.observeAsState
  54. import androidx.compose.runtime.mutableStateOf
  55. import androidx.compose.runtime.remember
  56. import androidx.compose.runtime.rememberCoroutineScope
  57. import androidx.compose.runtime.rememberUpdatedState
  58. import androidx.compose.runtime.saveable.rememberSaveable
  59. import androidx.compose.runtime.setValue
  60. import androidx.compose.ui.Alignment
  61. import androidx.compose.ui.Modifier
  62. import androidx.compose.ui.draw.alpha
  63. import androidx.compose.ui.draw.clip
  64. import androidx.compose.ui.draw.paint
  65. import androidx.compose.ui.focus.FocusRequester
  66. import androidx.compose.ui.focus.focusRequester
  67. import androidx.compose.ui.focus.onFocusChanged
  68. import androidx.compose.ui.graphics.Color
  69. import androidx.compose.ui.graphics.ColorFilter
  70. import androidx.compose.ui.graphics.painter.Painter
  71. import androidx.compose.ui.input.key.Key
  72. import androidx.compose.ui.input.key.KeyEventType
  73. import androidx.compose.ui.input.key.key
  74. import androidx.compose.ui.input.key.onKeyEvent
  75. import androidx.compose.ui.input.key.type
  76. import androidx.compose.ui.layout.ContentScale
  77. import androidx.compose.ui.platform.LocalContext
  78. import androidx.compose.ui.platform.LocalLifecycleOwner
  79. import androidx.compose.ui.res.colorResource
  80. import androidx.compose.ui.res.painterResource
  81. import androidx.compose.ui.text.AnnotatedString
  82. import androidx.compose.ui.text.TextStyle
  83. import androidx.compose.ui.unit.TextUnit
  84. import androidx.compose.ui.unit.dp
  85. import androidx.compose.ui.unit.sp
  86. import androidx.compose.ui.window.DialogProperties
  87. import androidx.constraintlayout.compose.ConstraintLayout
  88. import androidx.constraintlayout.compose.Dimension
  89. import androidx.lifecycle.Lifecycle
  90. import androidx.lifecycle.LifecycleEventObserver
  91. import androidx.lifecycle.LifecycleOwner
  92. import androidx.lifecycle.viewmodel.compose.viewModel
  93. import androidx.navigation.NavHostController
  94. import com.vpn.fastestvpnservice.MainActivity
  95. import com.vpn.fastestvpnservice.R
  96. import com.vpn.fastestvpnservice.beans.Protocol
  97. import com.vpn.fastestvpnservice.beans.Server
  98. import com.vpn.fastestvpnservice.beans.isDarkTheme
  99. import com.vpn.fastestvpnservice.beans.toChangeServer
  100. import com.vpn.fastestvpnservice.constants.AppEnum
  101. import com.vpn.fastestvpnservice.constants.smartConnect
  102. import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
  103. import com.vpn.fastestvpnservice.interfaces.ServerCallbacksTV
  104. import com.vpn.fastestvpnservice.navigation.isFirstItemFocused
  105. import com.vpn.fastestvpnservice.navigation.isFirstItemPressed
  106. import com.vpn.fastestvpnservice.navigation.isHomeScreenPressed
  107. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.StringDown
  108. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.StringDownUnit
  109. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.StringUp
  110. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.StringUpUnit
  111. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.isServerDialog
  112. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.navHostController1
  113. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.protocolObj
  114. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.serverObj
  115. import com.vpn.fastestvpnservice.screens.serverListViewModelSplash
  116. import com.vpn.fastestvpnservice.sealedClass.ScreenTV
  117. import com.vpn.fastestvpnservice.ui.theme.customTypography
  118. import com.vpn.fastestvpnservice.ui.theme.customTypography2
  119. import com.vpn.fastestvpnservice.utils.Utils
  120. import com.vpn.fastestvpnservice.utils.VPNConnectionsUtil
  121. import com.vpn.fastestvpnservice.utils.isTablet
  122. import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
  123. import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
  124. import com.wireguard.android.backend.GoBackend
  125. import de.blinkt.openvpn.core.App
  126. import java.util.Locale
  127. lateinit var vpnConnectionsUtil: VPNConnectionsUtil
  128. var isProtocolDialog: MutableState<Boolean> = mutableStateOf(false)
  129. var isLocationsEnabled: MutableState<Boolean> = mutableStateOf(false)
  130. var isDedicatedIpEnabled: MutableState<Boolean> = mutableStateOf(false)
  131. var isStreamingEnabled: MutableState<Boolean> = mutableStateOf(false)
  132. var isDvpnEnabled: MutableState<Boolean> = mutableStateOf(false)
  133. var isP2pEnabled: MutableState<Boolean> = mutableStateOf(false)
  134. var locations: MutableList<Server> = ArrayList<Server>()
  135. var dedicatedIP: MutableList<Server> = ArrayList<Server>()
  136. var streaming: MutableList<Server> = ArrayList<Server>()
  137. var dvpn: MutableList<Server> = ArrayList<Server>()
  138. var p2p: MutableList<Server> = ArrayList<Server>()
  139. val onServerTV = object : ServerCallbacksTV {
  140. @Composable
  141. override fun onServerSelected(
  142. context: Context, homeViewModel: HomeViewModel,
  143. onClick: () -> Unit, isServerDialogShown: Boolean, server: Server
  144. ) {
  145. val vpnConnectionsUtil = VPNConnectionsUtil(context, activityGlobal, homeViewModel)
  146. val basePreferenceHelper = BasePreferenceHelper(context)
  147. // val serverListViewModel: ServerListViewModel = viewModel{
  148. // ServerListViewModel(context)
  149. // }
  150. Log.d("ServerCallbacks", "onServerSelected called! : ${server.server_name}")
  151. val lastServer = basePreferenceHelper.getConnectedServer()
  152. val connectState = basePreferenceHelper.getConnectState()
  153. if (isServerDialogShown) {
  154. Log.d("ServerCallbacks", "onServerSelected true!")
  155. if (connectState == 2) {
  156. Log.d("ServerCallbacks", "onServerSelected isVPNConnected!")
  157. if (lastServer?.id != server.id) {
  158. isServerDialog.value = true
  159. serverObj.value = server
  160. }
  161. else {
  162. basePreferenceHelper.setConnectedServer(server)
  163. basePreferenceHelper.setServerObject(server)
  164. }
  165. } else {
  166. serverListViewModelSplash.setRecentlyConnectedServer(server)
  167. basePreferenceHelper.setConnectedServer(server)
  168. basePreferenceHelper.setServerObject(server)
  169. vpnConnectionsUtil.startVpn()
  170. }
  171. }
  172. else {
  173. Log.d("ServerCallbacks", "onServerSelected else")
  174. vpnConnectionsUtil.startVpn()
  175. }
  176. MainActivity.isSelectedServersShown = true
  177. onClick()
  178. }
  179. override fun onChangeProtocol(
  180. protocol: Protocol,
  181. context: Context,
  182. serverListViewModel: ServerListViewModel
  183. ) {
  184. val prefHelper = BasePreferenceHelper(context)
  185. // val wg = VPNConnectionsUtil(context, act , homeViewModel1)
  186. protocolObj.value = protocol
  187. val connectState = prefHelper.getConnectState()
  188. if (getEnableProtocols(protocol.title, prefHelper)) {
  189. Log.d("OnChangeProtocol", "getEnableProtocols yes!")
  190. if (prefHelper.getProtocol().index != protocol.index) {
  191. if (connectState == 2) {
  192. navHostController1.popBackStack()
  193. isProtocolDialog.value = true
  194. }
  195. else {
  196. prefHelper.saveProtocol(protocol = protocol)
  197. val lastServer = prefHelper.getConnectedServer()
  198. val serverList = prefHelper.getServerData()
  199. // val serverList = serverListViewModelSplash.liveDataGetServersGlobal.value
  200. if (lastServer != null) {
  201. val serverProtocol = serverListViewModel.getFilteredServerByProtocolChanged(serverList, lastServer, protocol)
  202. if (serverProtocol.isFound) {
  203. prefHelper.setServerObject(serverProtocol.server)
  204. val lastServer1 = prefHelper.getServerObject()
  205. }
  206. }
  207. serverListViewModelSplash.setCountryDataTV()
  208. }
  209. }
  210. }
  211. else {
  212. // Screen.Subscription.isTrue = true
  213. // navHostController1.let {
  214. // it.navigate(Screen.Subscription.route)
  215. // }
  216. }
  217. }
  218. }
  219. lateinit var activityGlobal: ComponentActivity
  220. @Composable
  221. fun HomeTV(
  222. navHostController: NavHostController,
  223. settingsNavHostController: NavHostController,
  224. activity: ComponentActivity
  225. ) {
  226. activityGlobal = activity
  227. navHostController1 = navHostController
  228. val context = LocalContext.current
  229. val basePreferenceHelper = BasePreferenceHelper(context)
  230. val prefHelper = BasePreferenceHelper(context)
  231. val scope = rememberCoroutineScope()
  232. val homeViewModel: HomeViewModel = viewModel{
  233. HomeViewModel(context, scope)
  234. }
  235. var isConnect: Int? = homeViewModel.isConnect.observeAsState().value
  236. isConnect = basePreferenceHelper.getConnectState()
  237. val focusRequester1 = remember { FocusRequester() }
  238. val focusRequester2 = remember { FocusRequester() }
  239. val focusRequester3 = remember { FocusRequester() }
  240. var isButtonFocused by remember { mutableStateOf(false) }
  241. val vpnConnectionsUtil = VPNConnectionsUtil(context, activity, homeViewModel)
  242. OnLifecycleEvent { owner, event ->
  243. when (event) {
  244. Lifecycle.Event.ON_RESUME -> {
  245. Log.d("test_home_resume", "ON_RESUME: Home Screen!")
  246. navHostController1 = navHostController
  247. try {
  248. App.backend?.runningTunnelNames
  249. } catch (e: Exception) {
  250. val back = GoBackend(context)
  251. App.setBackend(back)
  252. App.backend = App.getBackend()
  253. }
  254. vpnConnectionsUtil.onResumeCallBack()
  255. homeViewModel.getIp()
  256. // var filterServerByConnectionCount = Server()
  257. // if (prefHelper.getServerObject() != null) {
  258. // prefHelper.getServerObject()?.let {
  259. // filterServerByConnectionCount = it
  260. // }
  261. // } else {
  262. // val smartServer = basePreferenceHelper.getSmartServerObject()
  263. // smartServer?.let {
  264. // filterServerByConnectionCount = it
  265. // }
  266. // }
  267. //
  268. // server = filterServerByConnectionCount
  269. //
  270. //// splashViewModel.serverDataApi()
  271. homeViewModel.validatePassword(
  272. prefHelper.getUser()?.userinfo?.email.toString(),
  273. prefHelper.getPassword().toString(),
  274. "TV",
  275. Build.VERSION.RELEASE
  276. )
  277. }
  278. Lifecycle.Event.ON_PAUSE -> {
  279. Log.d("test_home_resume", "ON_PAUSE: Home Screen!")
  280. vpnConnectionsUtil.onPauseCallBack()
  281. }
  282. Lifecycle.Event.ON_STOP -> {
  283. Log.d("test_home_resume", "ON_STOP: Home Screen!")
  284. vpnConnectionsUtil.onStopCallBack()
  285. }
  286. Lifecycle.Event.ON_DESTROY -> {
  287. Log.d("test_home_resume", "ON_DESTROY: Home Screen!")
  288. vpnConnectionsUtil.onPauseCallBack()
  289. }
  290. else -> {
  291. Log.d("test_home_resume", "else: Home Screen!")
  292. }
  293. }
  294. }
  295. val validateResponse = homeViewModel.liveDataValidate.observeAsState().value
  296. validateResponse?.let {
  297. Log.d("test_api_validate", "home => ${it.status} ${it.message}")
  298. if (!it.status) {
  299. basePreferenceHelper.setLoggedInState(false)
  300. basePreferenceHelper.clearAllData()
  301. settingsNavHostController.popBackStack()
  302. settingsNavHostController.navigate(ScreenTV.LoginTV.route)
  303. }
  304. homeViewModel._mutableLiveDataValidate.value = null
  305. }
  306. if (isHomeScreenPressed.value) {
  307. LaunchedEffect(key1 = Unit) {
  308. focusRequester1.requestFocus()
  309. }
  310. isHomeScreenPressed.value = false
  311. }
  312. var isLaunched by rememberSaveable { mutableStateOf(true) }
  313. if (isLaunched) {
  314. Log.d("test_launch","liveDataGetServersGlobal")
  315. val countries = serverListViewModelSplash.liveDataGetServersGlobal.value
  316. countries?.forEachIndexed { index, serverData ->
  317. Log.d("test_serverlist_tv","$index ${serverData?.name} ${serverData?.servers?.size}")
  318. if (serverData?.name?.equals("Servers") == true) {
  319. serverData.servers?.let { locations = it }
  320. if (locations.size > 0) isLocationsEnabled.value = true
  321. }
  322. else if (serverData?.name?.equals("Dedicated IP") == true) {
  323. serverData.servers?.let { dedicatedIP = it }
  324. if (dedicatedIP.size > 0) isDedicatedIpEnabled.value = true
  325. }
  326. else if (serverData?.name?.equals("Streaming") == true) {
  327. serverData.servers?.let { streaming = it }
  328. if (streaming.size > 0) isStreamingEnabled.value = true
  329. }
  330. else if (serverData?.name?.equals("D-VPN") == true) {
  331. serverData.servers?.let { dvpn = it }
  332. if (dvpn.size > 0) isDvpnEnabled.value = true
  333. }
  334. else if (serverData?.name?.equals("P2P") == true) {
  335. serverData.servers?.let { p2p = it }
  336. if (p2p.size > 0) isP2pEnabled.value = true
  337. }
  338. }
  339. isLaunched = false
  340. }
  341. // BackHandler {
  342. // Toast.makeText(
  343. // context, "BackHandler Home TV", Toast.LENGTH_SHORT
  344. // ).show()
  345. // }
  346. Column(
  347. modifier = Modifier
  348. .background(MaterialTheme.colorScheme.background)
  349. .fillMaxSize(),
  350. ) {
  351. if (isServerDialog.value) {
  352. ShowServerDialogTV(
  353. basePreferenceHelper,
  354. vpnConnectionsUtil
  355. )
  356. }
  357. if (isProtocolDialog.value) {
  358. isFirstItemPressed.value = true
  359. isFirstItemFocused.value = true
  360. ShowProtocolDialogTV(
  361. basePreferenceHelper,
  362. vpnConnectionsUtil,
  363. serverListViewModelSplash
  364. )
  365. }
  366. // 1st box
  367. ConstraintLayout(modifier = Modifier
  368. .fillMaxSize()
  369. .weight(0.6f)
  370. .background(Color.Transparent)
  371. )
  372. {
  373. val (firstComposable, secondComposable) = createRefs()
  374. val guideline = createGuidelineFromTop(0.7f)
  375. Box(
  376. modifier = Modifier
  377. .constrainAs(firstComposable) {
  378. top.linkTo(parent.top)
  379. bottom.linkTo(guideline)
  380. start.linkTo(parent.start)
  381. end.linkTo(parent.end)
  382. width = Dimension.fillToConstraints
  383. height = Dimension.fillToConstraints
  384. }
  385. .background(Color.Transparent)
  386. ) {
  387. Image(
  388. modifier = Modifier
  389. .fillMaxWidth()
  390. .fillMaxHeight()
  391. .padding(top = 0.dp),
  392. // painter = if (isConnect == App.CONNECTED) blueBackgroundTV() else pinkBackgroundTV(),
  393. painter = if (isConnect == App.CONNECTED) blueBackgroundTV()
  394. else pinkBackgroundTV(),
  395. contentDescription = "Background Color",
  396. contentScale = ContentScale.FillBounds,
  397. )
  398. Image(
  399. modifier = Modifier
  400. .fillMaxWidth()
  401. .fillMaxHeight()
  402. .padding(bottom = 0.dp)
  403. .alpha(if (isDarkTheme.value) 0.1F else 0.6F),
  404. // .alpha(0.6F),
  405. painter = painterResource(id = R.drawable.map_home3x),
  406. contentDescription = "Home Map",
  407. contentScale = ContentScale.FillWidth,
  408. )
  409. Column(
  410. modifier = Modifier
  411. .fillMaxWidth()
  412. .fillMaxHeight()
  413. .padding(bottom = 85.dp)
  414. // .offset(y = -(118).dp)
  415. .background(Color.Transparent),
  416. horizontalAlignment = Alignment.CenterHorizontally,
  417. verticalArrangement = Arrangement.Bottom
  418. ) {
  419. val serverObj = basePreferenceHelper.getConnectedServer()
  420. val serverDis = basePreferenceHelper.getIpinfo()
  421. var ipInfo = homeViewModel.mutableLiveDataIpInfo.observeAsState().value?.query
  422. ipInfo = if (isConnect == App.CONNECTED) serverObj?.ip.toString() else serverDis?.query
  423. AddText(
  424. text = "IP ${ipInfo ?: ""}",
  425. size = 18.sp,
  426. // color = MaterialTheme.colorScheme.primary,
  427. color = MaterialTheme.colorScheme.primary,
  428. style = MaterialTheme.typography.customTypography.headlineLarge.copy(
  429. fontSize = 18.sp
  430. )
  431. )
  432. Row(
  433. verticalAlignment = Alignment.CenterVertically,
  434. modifier = Modifier
  435. .background(Color.Transparent)
  436. .padding(top = 5.dp)
  437. ) {
  438. if (isConnect == App.CONNECTED) {
  439. val image = Utils.getDrawable(context, serverObj?.iso)
  440. if (image != 0) {
  441. Image(
  442. painter = painterResource(id = image),
  443. contentDescription = "Country",
  444. modifier = Modifier
  445. .padding(end = 6.dp)
  446. .size(15.dp)
  447. .clip(CircleShape)
  448. .paint(
  449. painter = painterResource(id = image),
  450. contentScale = ContentScale.FillBounds
  451. )
  452. )
  453. }
  454. AddText(
  455. text = "${serverObj?.server_name ?: ""}, ${serverObj?.country ?: ""}",
  456. size = 16.sp,
  457. color = MaterialTheme.colorScheme.primary,
  458. isTablet()
  459. )
  460. } else {
  461. val image = Utils.getDrawable(context, serverDis?.countryCode)
  462. Log.d("image_logo", "$image ${serverDis?.countryCode}")
  463. if (image != 0) {
  464. Image(
  465. painter = painterResource(id = image),
  466. contentDescription = "Server",
  467. modifier = Modifier
  468. .padding(end = 6.dp)
  469. .size(15.dp)
  470. .clip(CircleShape)
  471. .paint(
  472. painter = painterResource(id = image),
  473. contentScale = ContentScale.FillBounds
  474. )
  475. )
  476. }
  477. AddText(
  478. text = "${serverDis?.city ?: ""}, ${serverDis?.country ?: ""}",
  479. size = 16.sp,
  480. color = MaterialTheme.colorScheme.primary,
  481. isTablet()
  482. )
  483. }
  484. }
  485. when (isConnect) {
  486. App.CONNECTED -> {
  487. AddText(
  488. text = "Connected",
  489. size = 18.sp,
  490. color = MaterialTheme.colorScheme.surfaceContainerHigh,
  491. // color = colorResource(id = R.color.light_blue_2),
  492. style = MaterialTheme.typography.customTypography.displaySmall.copy(
  493. fontSize = 18.sp
  494. )
  495. )
  496. }
  497. App.DISCONNECTED -> {
  498. AddText(
  499. text = "Disconnected",
  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. App.CONNECTING -> {
  509. AddText(
  510. text = "Connecting...",
  511. size = 18.sp,
  512. color = MaterialTheme.colorScheme.surfaceTint,
  513. // color = colorResource(id = R.color.maroon_text),
  514. style = MaterialTheme.typography.customTypography.displaySmall.copy(
  515. fontSize = 18.sp
  516. )
  517. )
  518. }
  519. }
  520. }
  521. }
  522. Box(
  523. modifier = Modifier
  524. .constrainAs(secondComposable) {
  525. top.linkTo(guideline)
  526. bottom.linkTo(firstComposable.bottom)
  527. start.linkTo(parent.start)
  528. end.linkTo(parent.end)
  529. width = Dimension.value(150.dp)
  530. height = Dimension.value(150.dp)
  531. }
  532. .background(Color.Transparent)
  533. ) {
  534. val color = if (isButtonFocused && isConnect == App.CONNECTED) colorResource(id = R.color.dark_blue_gray_text)
  535. else if (isButtonFocused) colorResource(id = R.color.maroon_text)
  536. else colorResource(id = R.color.transparent)
  537. IconButton(
  538. onClick = {
  539. // Toast.makeText(
  540. // context, "Connect onClick{}", Toast.LENGTH_SHORT
  541. // ).show()
  542. // val connectedServer = basePreferenceHelper.getConnectedServer()
  543. // val serverObject = basePreferenceHelper.getServerObject()
  544. // Log.d(
  545. // "test_conn_ser_obj",
  546. // "cs = ${connectedServer?.server_name} so = ${serverObject?.server_name}"
  547. // )
  548. // Log.d("isConnect_State", "onClick{} -> $isConnect")
  549. // Log.d("isConnect_State_vpn", "onClick{} -> $isConnect")
  550. // prefHelper.getProduct()?.identifier.let {
  551. // val identifier = it
  552. //
  553. // if (identifier == AppEnum.FREE.key) {
  554. // Log.d("isConnect_State", "identifier -> $identifier")
  555. // Screen.Subscription.isTrue = true
  556. // navHostController.navigate(
  557. // Screen.Subscription.route
  558. // )
  559. //
  560. // } else {
  561. //
  562. // prefHelper.getServerObject()?.let {
  563. // prefHelper.setConnectedServer(it)
  564. // }
  565. // Log.d("isConnect_State", "identifier -> $identifier")
  566. // if (isConnect == App.CONNECTED || isConnect == App.CONNECTING) {
  567. // Log.d("isConnect_State_vpn", "stopVPN")
  568. // vpnConnectionsUtil.stopVpn()
  569. // homeViewModel.getIp()
  570. // } else {
  571. // Log.d("isConnect_State_vpn", "startVPN")
  572. //
  573. // if (basePreferenceHelper.getServerObject() != null) {
  574. // vpnConnectionsUtil.startVpn()
  575. // } else {
  576. // toChangeServer.value = false
  577. // navHostController.navigate(
  578. // Screen.ServerList.route
  579. // )
  580. // Screen.ServerList.isTrue = true
  581. // Log.d("button_click_change", "Pressed")
  582. // }
  583. // }
  584. //
  585. //
  586. // val widgetIntent = Intent(context, SimpleAppWidget::class.java)
  587. // widgetIntent.action = SimpleAppWidget.ACTION_CHANGE_SERVER
  588. // context.sendBroadcast(widgetIntent)
  589. // }
  590. // }
  591. },
  592. modifier = Modifier
  593. .padding(bottom = 0.dp)
  594. .size(150.dp)
  595. .onKeyEvent {
  596. when (it.key) {
  597. Key.DirectionDown -> {
  598. Log.d("test_settings_keys", "DirectionDown")
  599. if (it.type == KeyEventType.KeyDown) {
  600. focusRequester2.requestFocus()
  601. }
  602. true
  603. }
  604. else -> {
  605. true
  606. }
  607. }
  608. }
  609. .focusRequester(focusRequester1)
  610. .background(Color.Transparent)
  611. .onFocusChanged {
  612. isButtonFocused = it.isFocused
  613. }
  614. .clickable {
  615. val connectedServer = basePreferenceHelper.getConnectedServer()
  616. val serverObject = basePreferenceHelper.getServerObject()
  617. prefHelper.getProduct()?.identifier.let {
  618. val identifier = it
  619. if (identifier == AppEnum.FREE.key) {
  620. } else {
  621. Log.d("isConnect_State_vpn", "else connect button $isConnect")
  622. prefHelper
  623. .getServerObject()
  624. ?.let {
  625. Log.d(
  626. "isConnect_State_vpn",
  627. "getServerObject ${it.server_name}"
  628. )
  629. prefHelper.setConnectedServer(it)
  630. }
  631. if (isConnect == App.CONNECTED || isConnect == App.CONNECTING) {
  632. Log.d("isConnect_State_vpn", "stopVPN")
  633. vpnConnectionsUtil.stopVpn()
  634. homeViewModel.getIp()
  635. } else {
  636. Log.d("isConnect_State_vpn", "Disconnected")
  637. if (basePreferenceHelper.getServerObject() != null) {
  638. Log.d("isConnect_State_vpn", "startVpn")
  639. vpnConnectionsUtil.startVpn()
  640. } else {
  641. Log.d("isConnect_State_vpn", "else ServerListTV")
  642. toChangeServer.value = false
  643. navHostController.navigate(
  644. ScreenTV.ServerListTV.route
  645. )
  646. }
  647. }
  648. }
  649. }
  650. // if (isConnect == App.DISCONNECTED) homeViewModel.setConnectState(App.CONNECTED)
  651. // else if (isConnect == App.CONNECTED) homeViewModel.setConnectState(App.DISCONNECTED)
  652. }
  653. .focusable()
  654. ,
  655. )
  656. {
  657. if (isConnect == App.CONNECTED) {
  658. Image(
  659. painter = if (isDarkTheme.value) painterResource(id = R.drawable.iv_connect_dark)
  660. else painterResource(id = R.drawable.iv_connect),
  661. // painter = painterResource(id = R.drawable.iv_connect),
  662. contentDescription = "Home Map",
  663. contentScale = ContentScale.FillBounds,
  664. modifier = Modifier
  665. .size(150.dp)
  666. .border(
  667. BorderStroke(
  668. 2.dp, color
  669. ), shape = CircleShape
  670. )
  671. )
  672. } else {
  673. Image(
  674. painter = if (isDarkTheme.value) painterResource(id = R.drawable.iv_disconnect_dark)
  675. else painterResource(id = R.drawable.iv_disconnect),
  676. // painter = painterResource(id = R.drawable.iv_disconnect),
  677. contentDescription = "Home Map",
  678. contentScale = ContentScale.FillBounds,
  679. modifier = Modifier
  680. .size(150.dp)
  681. .border(
  682. BorderStroke(
  683. 2.dp, color
  684. ), shape = CircleShape
  685. )
  686. )
  687. }
  688. }
  689. }
  690. }
  691. // 2nd box
  692. Box(
  693. modifier = Modifier
  694. .background(MaterialTheme.colorScheme.background)
  695. .fillMaxSize()
  696. .weight(0.4f)
  697. // .background(Color.Transparent),
  698. ) {
  699. Column(
  700. modifier = Modifier.fillMaxSize(),
  701. verticalArrangement = Arrangement.Center
  702. )
  703. {
  704. if (isConnect != App.CONNECTED) {
  705. Box(
  706. modifier = Modifier
  707. .fillMaxWidth(fraction = 0.4f)
  708. .padding(horizontal = 0.dp)
  709. .padding(vertical = 2.dp)
  710. .height(90.dp)
  711. .border(
  712. border = BorderStroke(2.dp, MaterialTheme.colorScheme.onBackground),
  713. shape = RoundedCornerShape(28.dp)
  714. )
  715. .background(
  716. shape = RoundedCornerShape(28.dp),
  717. color = MaterialTheme.colorScheme.onBackground
  718. )
  719. .align(Alignment.CenterHorizontally),
  720. ) {
  721. AddRowSmartTV(
  722. navHostController,
  723. basePreferenceHelper,
  724. context,
  725. isTablet(),
  726. focusRequester2,
  727. homeViewModel
  728. )
  729. var smartServer = basePreferenceHelper.getSmartServerObject()
  730. val recommended = basePreferenceHelper.getRecommendedServerObject()
  731. val selectedSmartList = basePreferenceHelper.getSmartList()
  732. var isSmartButtonFocused by remember { mutableStateOf(false) }
  733. when(selectedSmartList) {
  734. smartConnect[0] -> {
  735. smartServer = basePreferenceHelper.getRecommendedServerObject()
  736. }
  737. smartConnect[1] -> {
  738. smartServer = basePreferenceHelper.getSmartServerObject() ?: recommended
  739. }
  740. smartConnect[2] -> {
  741. smartServer = basePreferenceHelper.getSmartServerObject() ?: recommended
  742. }
  743. else -> {}
  744. }
  745. val color = if (isSmartButtonFocused && isConnect == App.CONNECTED) MaterialTheme.colorScheme.primary
  746. else if (isSmartButtonFocused) MaterialTheme.colorScheme.primary
  747. else colorResource(id = R.color.blue_text)
  748. Button(
  749. onClick = {},
  750. modifier = Modifier
  751. .padding(start = 14.dp, end = 14.dp, bottom = 6.dp, top = 12.dp)
  752. .align(Alignment.BottomCenter)
  753. .background(
  754. MaterialTheme.colorScheme.onBackground,
  755. RoundedCornerShape(16.dp)
  756. )
  757. .border(2.dp, color, RoundedCornerShape(16.dp))
  758. .onFocusChanged {
  759. isSmartButtonFocused = it.isFocused
  760. }
  761. .onKeyEvent {
  762. when (it.key) {
  763. Key.DirectionLeft -> { true }
  764. Key.DirectionRight -> { true }
  765. else -> false
  766. }
  767. }
  768. // .focusable()
  769. .clickable {
  770. Log.d(
  771. "test_button",
  772. "onClick Smart Connect ${smartServer?.server_name}"
  773. )
  774. basePreferenceHelper.setSmartServerObject(smartServer)
  775. if (isConnect == App.CONNECTED) {
  776. Log.d("isConnect_State_vpn", "stopVPN")
  777. val lastServer = basePreferenceHelper.getConnectedServer()
  778. Log.d(
  779. "test_conn_ser_obj",
  780. "smart => ${lastServer?.server_name} ${smartServer?.server_name}"
  781. )
  782. if (lastServer?.id != smartServer?.id) {
  783. isServerDialog.value = true
  784. if (smartServer != null) {
  785. serverObj.value = smartServer
  786. }
  787. } else {
  788. vpnConnectionsUtil.stopVpn()
  789. }
  790. // vpnConnectionsUtil.stopVpn()
  791. // Handler().postDelayed(Runnable {
  792. // vpnConnectionsUtil.startVpn()
  793. // }, 500)
  794. // homeViewModel.getIp()
  795. } else if (isConnect == App.CONNECTING) {
  796. vpnConnectionsUtil.stopVpn()
  797. } else if (isConnect == App.DISCONNECTED) {
  798. Log.d("isConnect_State_vpn", "startVPN")
  799. basePreferenceHelper.setConnectedServer(smartServer)
  800. if (smartServer != null) {
  801. serverListViewModelSplash.setRecentlyConnectedServer(
  802. smartServer
  803. )
  804. }
  805. vpnConnectionsUtil.startVpn()
  806. }
  807. }
  808. .fillMaxWidth()
  809. .height(35.dp),
  810. shape = RoundedCornerShape(16.dp),
  811. colors = ButtonDefaults.buttonColors(
  812. contentColor = colorResource(id = R.color.white),
  813. containerColor = colorResource(id = R.color.blue_text),
  814. ),
  815. ) {
  816. Text(
  817. text = "Smart Connect",
  818. style = MaterialTheme.typography.customTypography.labelLarge.copy(
  819. fontSize = 16.sp, lineHeight = 0.sp
  820. ),
  821. modifier = Modifier.background(Color.Transparent)
  822. )
  823. }
  824. }
  825. /* Select Server Box*/
  826. // if (isConnect != App.CONNECTED) { }
  827. // Spacer(modifier = Modifier.weight(1f))
  828. var isLayoutFocused by remember { mutableStateOf(false) }
  829. val color = if (isLayoutFocused && isConnect == App.CONNECTED) MaterialTheme.colorScheme.primary
  830. else if (isLayoutFocused) MaterialTheme.colorScheme.primary
  831. else MaterialTheme.colorScheme.onBackground
  832. Box(
  833. modifier = Modifier
  834. .fillMaxWidth(fraction = 0.4f)
  835. .padding(horizontal = 0.dp, vertical = 2.dp)
  836. .padding(top = 0.dp)
  837. .height(50.dp)
  838. .onKeyEvent {
  839. if (it.type == KeyEventType.KeyDown && it.key == Key.DirectionDown) {
  840. isFirstItemPressed.value = true
  841. true
  842. } else {
  843. false
  844. }
  845. }
  846. .onFocusChanged {
  847. isLayoutFocused = it.isFocused
  848. }
  849. .focusable()
  850. .clickable(
  851. indication = null,
  852. interactionSource = remember { MutableInteractionSource() }
  853. ) {
  854. toChangeServer.value = false
  855. navHostController.navigate(
  856. ScreenTV.ServerListTV.route
  857. )
  858. }
  859. .border(
  860. border = BorderStroke(2.dp, color),
  861. shape = RoundedCornerShape(28.dp)
  862. )
  863. .background(
  864. shape = RoundedCornerShape(28.dp),
  865. color = MaterialTheme.colorScheme.onBackground
  866. )
  867. .align(Alignment.CenterHorizontally),
  868. contentAlignment = Alignment.CenterStart,
  869. ) {
  870. AddRowSelectServerTV(navHostController, isTablet())
  871. }
  872. }
  873. else {
  874. var isFeedbackClicked by remember { mutableStateOf(prefHelper.getFeedbackState()) }
  875. var isDelayedFeedbackClicked by remember { mutableStateOf(isFeedbackClicked) }
  876. var isThumbUpClicked by remember { mutableStateOf(App.isThumbUpClicked) }
  877. var isThumbDownClicked by remember { mutableStateOf(App.isThumbDownClicked) }
  878. var isRipple = false
  879. var isThumbUpFocused by remember { mutableStateOf(false) }
  880. var isThumbDownFocused by remember { mutableStateOf(false) }
  881. Box(
  882. modifier = Modifier
  883. .fillMaxWidth(fraction = 0.4f)
  884. .padding(horizontal = 0.dp)
  885. .padding(vertical = 5.dp)
  886. .height(90.dp)
  887. .align(Alignment.CenterHorizontally)
  888. // .border(
  889. // border = BorderStroke(0.dp, Color.Blue),
  890. // shape = RoundedCornerShape(28.dp)
  891. // )
  892. .background(
  893. color = Color.Transparent
  894. ),
  895. ) {
  896. Row(
  897. modifier = Modifier
  898. .padding(0.dp)
  899. .background(Color.Transparent),
  900. horizontalArrangement = Arrangement.SpaceAround,
  901. verticalAlignment = Alignment.CenterVertically
  902. ) {
  903. Surface(
  904. modifier = Modifier
  905. .weight(1f)
  906. .fillMaxHeight()
  907. .padding(end = 5.dp)
  908. .border(
  909. width = 1.dp,
  910. color = MaterialTheme.colorScheme.onBackground,
  911. shape = RoundedCornerShape(24.dp)
  912. )
  913. .background(Color.Transparent),
  914. shape = RoundedCornerShape(24.dp)
  915. ) {
  916. Column(
  917. modifier = Modifier
  918. .background(MaterialTheme.colorScheme.onBackground)
  919. .border(
  920. width = 1.dp,
  921. color = MaterialTheme.colorScheme.onBackground,
  922. shape = RoundedCornerShape(24.dp)
  923. ),
  924. verticalArrangement = Arrangement.SpaceEvenly,
  925. horizontalAlignment = Alignment.CenterHorizontally,
  926. ) {
  927. Image(
  928. painter = painterResource(id = R.drawable.greenarrow3x),
  929. contentDescription = "Green Arrow",
  930. modifier = Modifier
  931. .size(30.dp)
  932. )
  933. Text(
  934. text = "Download",
  935. style = MaterialTheme.typography.customTypography.displayMedium.copy(
  936. color = MaterialTheme.colorScheme.onTertiary
  937. ),
  938. modifier = Modifier.alpha(0.6F)
  939. )
  940. Row(
  941. horizontalArrangement = Arrangement.SpaceAround,
  942. verticalAlignment = Alignment.CenterVertically
  943. ) {
  944. Text(
  945. text = String.format(Locale.US, "%.2f", StringDown.value),
  946. style = MaterialTheme.typography.customTypography.displayLarge.copy(
  947. color = MaterialTheme.colorScheme.primary
  948. )
  949. )
  950. Text(
  951. text = " ${StringDownUnit.value}",
  952. style = MaterialTheme.typography.customTypography2.labelSmall.copy(
  953. color = MaterialTheme.colorScheme.primary
  954. ),
  955. modifier = Modifier.alpha(0.5F)
  956. )
  957. }
  958. }
  959. }
  960. Surface(
  961. modifier = Modifier
  962. .weight(1f)
  963. .fillMaxHeight()
  964. .padding(start = 5.dp)
  965. .border(
  966. width = 1.dp,
  967. color = MaterialTheme.colorScheme.onBackground,
  968. shape = RoundedCornerShape(24.dp)
  969. )
  970. .background(Color.Transparent),
  971. shape = RoundedCornerShape(24.dp)
  972. ) {
  973. Column(
  974. modifier = Modifier
  975. .background(MaterialTheme.colorScheme.onBackground)
  976. .border(
  977. width = 1.dp,
  978. color = MaterialTheme.colorScheme.onBackground,
  979. shape = RoundedCornerShape(24.dp)
  980. ),
  981. verticalArrangement = Arrangement.SpaceEvenly,
  982. horizontalAlignment = Alignment.CenterHorizontally
  983. ) {
  984. Image(
  985. painter = painterResource(id = R.drawable.yellowarrow3x),
  986. contentDescription = "Yellow Arrow",
  987. modifier = Modifier
  988. .size(30.dp)
  989. )
  990. Text(
  991. text = "Upload",
  992. style = MaterialTheme.typography.customTypography.displayMedium.copy(
  993. color = MaterialTheme.colorScheme.onTertiary
  994. ),
  995. modifier = Modifier.alpha(0.6F)
  996. )
  997. Row(
  998. horizontalArrangement = Arrangement.SpaceAround,
  999. verticalAlignment = Alignment.CenterVertically
  1000. ) {
  1001. Text(
  1002. text = String.format(Locale.US,"%.2f", StringUp.value),
  1003. style = MaterialTheme.typography.customTypography.displayLarge.copy(
  1004. color = MaterialTheme.colorScheme.primary
  1005. )
  1006. )
  1007. Text(
  1008. text = " ${StringUpUnit.value}",
  1009. style = MaterialTheme.typography.customTypography2.labelSmall.copy(
  1010. color = MaterialTheme.colorScheme.primary
  1011. ),
  1012. modifier = Modifier.alpha(0.5F)
  1013. )
  1014. }
  1015. }
  1016. }
  1017. }
  1018. }
  1019. val backgroundColor by animateColorAsState(
  1020. targetValue = if (isDelayedFeedbackClicked) colorResource(id = R.color.yellow_feedback)
  1021. else MaterialTheme.colorScheme.outlineVariant, label = "Color"
  1022. )
  1023. Box(
  1024. modifier = Modifier
  1025. .padding(horizontal = 0.dp)
  1026. .padding(vertical = 5.dp)
  1027. .fillMaxWidth(fraction = 0.4f)
  1028. .height(55.dp)
  1029. .background(
  1030. backgroundColor,
  1031. shape = RoundedCornerShape(12.dp)
  1032. )
  1033. .border(
  1034. width = 1.dp,
  1035. color = Color.Transparent,
  1036. shape = RoundedCornerShape(12.dp)
  1037. )
  1038. .align(Alignment.CenterHorizontally)
  1039. ) {
  1040. Row(
  1041. modifier = Modifier
  1042. .fillMaxSize()
  1043. .padding(16.dp),
  1044. horizontalArrangement = Arrangement.SpaceBetween,
  1045. verticalAlignment = Alignment.CenterVertically
  1046. ) {
  1047. Text(
  1048. text = "How's your connection?",
  1049. style = MaterialTheme.typography.customTypography.titleSmall.copy(
  1050. color = Color.White
  1051. )
  1052. )
  1053. Row(
  1054. modifier = Modifier
  1055. .background(Color.Transparent),
  1056. horizontalArrangement = Arrangement.Center,
  1057. verticalAlignment = Alignment.CenterVertically
  1058. ) {
  1059. Image(
  1060. imageVector = Icons.Outlined.ThumbUp,
  1061. contentDescription = "Thumb Up",
  1062. modifier = Modifier
  1063. .padding(end = 25.dp)
  1064. .size(24.dp)
  1065. .focusRequester(focusRequester2)
  1066. .onKeyEvent {
  1067. if (it.type == KeyEventType.KeyDown && it.key == Key.DirectionDown) {
  1068. isFirstItemPressed.value = true
  1069. true
  1070. }
  1071. else if (it.type == KeyEventType.KeyDown && it.key == Key.DirectionLeft) {
  1072. true
  1073. }
  1074. else {
  1075. false
  1076. }
  1077. }
  1078. .onFocusChanged {
  1079. isThumbUpFocused = it.isFocused
  1080. }
  1081. .focusable()
  1082. .clickable(
  1083. indication = rememberRipple(
  1084. bounded = true,
  1085. color = colorResource(id = R.color.switch_green)
  1086. ),
  1087. interactionSource = remember { MutableInteractionSource() }
  1088. ) {
  1089. val connectedServer =
  1090. basePreferenceHelper.getConnectedServer()
  1091. val selectedProtocol =
  1092. basePreferenceHelper.getProtocol().full_name
  1093. if (!isFeedbackClicked) {
  1094. isFeedbackClicked = true
  1095. prefHelper.setFeedbackState(true)
  1096. isThumbUpClicked = true
  1097. App.isThumbUpClicked = true
  1098. isRipple = true
  1099. homeViewModel.feedback(
  1100. rating = 1,
  1101. server_id = connectedServer?.id,
  1102. server_ip = connectedServer?.ip.toString(),
  1103. protocol = selectedProtocol
  1104. )
  1105. }
  1106. }
  1107. ,
  1108. colorFilter = ColorFilter.tint(
  1109. if (isFeedbackClicked && isThumbUpClicked) colorResource(id = R.color.switch_green)
  1110. else if (isThumbUpFocused) colorResource(id = R.color.dark_blue_gray_text)
  1111. else colorResource(id = R.color.white)
  1112. )
  1113. )
  1114. Image(
  1115. imageVector = Icons.Outlined.ThumbDown,
  1116. contentDescription = "Thumb Down",
  1117. modifier = Modifier
  1118. .padding(end = 10.dp)
  1119. .size(24.dp)
  1120. .onFocusChanged {
  1121. isThumbDownFocused = it.isFocused
  1122. }
  1123. .onKeyEvent {
  1124. if (it.type == KeyEventType.KeyDown && it.key == Key.DirectionDown) {
  1125. isFirstItemPressed.value = true
  1126. true
  1127. }
  1128. else if (it.type == KeyEventType.KeyDown && it.key == Key.DirectionRight) {
  1129. true
  1130. }
  1131. else {
  1132. false
  1133. }
  1134. }
  1135. .focusable()
  1136. .clickable(
  1137. indication = rememberRipple(
  1138. bounded = true,
  1139. color = colorResource(id = R.color.Red)
  1140. ),
  1141. interactionSource = remember { MutableInteractionSource() }
  1142. ) {
  1143. val connectedServer =
  1144. basePreferenceHelper.getConnectedServer()
  1145. val selectedProtocol =
  1146. basePreferenceHelper.getProtocol().full_name
  1147. if (!isFeedbackClicked) {
  1148. isFeedbackClicked = true
  1149. prefHelper.setFeedbackState(true)
  1150. isThumbDownClicked = true
  1151. App.isThumbDownClicked = true
  1152. homeViewModel.feedback(
  1153. rating = 0,
  1154. server_id = connectedServer?.id,
  1155. server_ip = connectedServer?.ip.toString(),
  1156. protocol = selectedProtocol
  1157. )
  1158. }
  1159. },
  1160. colorFilter = ColorFilter.tint(
  1161. if (isFeedbackClicked && isThumbDownClicked) colorResource(id = R.color.Red)
  1162. else if (isThumbDownFocused) colorResource(id = R.color.dark_blue_gray_text)
  1163. else colorResource(id = R.color.white)
  1164. )
  1165. )
  1166. }
  1167. }
  1168. }
  1169. }
  1170. }
  1171. }
  1172. }
  1173. }
  1174. @OptIn(ExperimentalMaterial3Api::class)
  1175. @Composable
  1176. fun ColumnScope.ShowProtocolDialogTV(
  1177. prefHelper: BasePreferenceHelper,
  1178. wg: VPNConnectionsUtil,
  1179. serverListViewModel: ServerListViewModel
  1180. ) {
  1181. var isButtonFocused1 by remember { mutableStateOf(false) }
  1182. var isButtonFocused2 by remember { mutableStateOf(false) }
  1183. AlertDialog(
  1184. onDismissRequest = { isProtocolDialog.value = false },
  1185. properties = DialogProperties(),
  1186. modifier = Modifier
  1187. .fillMaxWidth()
  1188. .wrapContentHeight()
  1189. ) {
  1190. val lastServer = prefHelper.getConnectedServer()
  1191. val selectedProtocol = prefHelper.getProtocol()
  1192. val oldProtocolTitle = if (selectedProtocol.index == 0) AppEnum.AUTO_PROTOCOL.key else selectedProtocol.title
  1193. val newProtocolTitle = if (protocolObj.value.index == 0) AppEnum.AUTO_PROTOCOL.key else protocolObj.value.title
  1194. val serverList = prefHelper.getServerData()
  1195. // val serverList = serverListViewModelSplash.liveDataGetServersGlobal.value
  1196. var desiredServer = Server()
  1197. var isServerFound: Boolean = false
  1198. if (lastServer != null) {
  1199. val serverProtocol = serverListViewModel.getFilteredServerByProtocolChanged(serverList, lastServer,
  1200. protocolObj.value)
  1201. if (serverProtocol.isFound) {
  1202. desiredServer = serverProtocol.server
  1203. isServerFound = true
  1204. }
  1205. }
  1206. // serverListViewModelSplash.setCountryData()
  1207. // Log.d("server_protocol", "Home: $isServerFound ${desiredServer.id} ${desiredServer.server_name} ${desiredServer.ip} ${desiredServer.protocol} ${desiredServer.remoteId}")
  1208. Surface(
  1209. color = colorResource(id = R.color.white),
  1210. modifier = Modifier
  1211. .background(Color.Transparent)
  1212. .fillMaxWidth()
  1213. ,
  1214. shape = RoundedCornerShape(18.dp)
  1215. ) {
  1216. Column(
  1217. verticalArrangement = Arrangement.Top,
  1218. horizontalAlignment = Alignment.CenterHorizontally,
  1219. modifier = Modifier
  1220. .background(colorResource(id = R.color.white))
  1221. ) {
  1222. Log.d("islogoutClicked", "AlertDialog")
  1223. Text(text = "Confirm",
  1224. color = colorResource(id = R.color.dark_blue_gray_text),
  1225. style = MaterialTheme.typography.bodyMedium,
  1226. modifier = Modifier.padding(top = 45.dp)
  1227. )
  1228. Text(text = "Are you sure to switch from $oldProtocolTitle to $newProtocolTitle?",
  1229. color = colorResource(id = R.color.dark_blue_gray_text),
  1230. style = MaterialTheme.typography.labelSmall,
  1231. maxLines = 2,
  1232. modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 26.dp)
  1233. )
  1234. Row (
  1235. modifier = Modifier
  1236. .padding(top = 34.dp, bottom = 20.dp),
  1237. horizontalArrangement = Arrangement.SpaceBetween,
  1238. verticalAlignment = Alignment.Bottom
  1239. ) {
  1240. Button(
  1241. onClick = {
  1242. Log.d("ServerCallbacks", "No")
  1243. isProtocolDialog.value = false
  1244. },
  1245. modifier = Modifier
  1246. .padding(
  1247. start = 15.dp, end = 5.dp,
  1248. bottom = 0.dp, top = 0.dp
  1249. )
  1250. .onFocusChanged {
  1251. isButtonFocused1 = it.isFocused
  1252. }
  1253. .background(colorResource(id = R.color.transparent))
  1254. .weight(1F)
  1255. .height(52.dp),
  1256. shape = RoundedCornerShape(15.dp),
  1257. colors = ButtonDefaults.buttonColors(
  1258. contentColor = if (isButtonFocused1) colorResource(id = R.color.dark_blue_gray_text) else colorResource(id = R.color.white),
  1259. containerColor = colorResource(id = R.color.light_blue),
  1260. ),
  1261. border = BorderStroke(2.dp, if (isButtonFocused1) colorResource(id = R.color.dark_blue_gray_text) else colorResource(id = R.color.light_blue))
  1262. )
  1263. {
  1264. Text(text = "No",
  1265. style = MaterialTheme.typography.labelLarge)
  1266. Log.d("test_button", "RowScope")
  1267. }
  1268. Button(
  1269. onClick = {
  1270. Log.d("ServerCallbacks", "Yes")
  1271. val server = if (isServerFound) desiredServer else prefHelper.getConnectedServer()
  1272. prefHelper.setServerObject(server)
  1273. prefHelper.setConnectedServer(server)
  1274. prefHelper.saveProtocol(protocol = protocolObj.value)
  1275. wg.stopVpn()
  1276. Handler().postDelayed(Runnable {
  1277. wg.startVpn()
  1278. }, 500)
  1279. Log.d("ServerCallbacks", "Yes click => ${isProtocolDialog.value}")
  1280. isProtocolDialog.value = false
  1281. serverListViewModelSplash.setCountryData()
  1282. },
  1283. modifier = Modifier
  1284. .padding(
  1285. start = 5.dp, end = 15.dp,
  1286. bottom = 0.dp, top = 0.dp
  1287. )
  1288. .onFocusChanged {
  1289. isButtonFocused2 = it.isFocused
  1290. }
  1291. .background(colorResource(id = R.color.transparent))
  1292. .weight(1F)
  1293. .height(52.dp),
  1294. shape = RoundedCornerShape(15.dp),
  1295. colors = ButtonDefaults.buttonColors(
  1296. contentColor = if (isButtonFocused2) colorResource(id = R.color.dark_blue_gray_text) else colorResource(id = R.color.white),
  1297. containerColor = colorResource(id = R.color.red),
  1298. ),
  1299. border = BorderStroke(2.dp, if (isButtonFocused2) colorResource(id = R.color.dark_blue_gray_text) else colorResource(id = R.color.red))
  1300. // border = BorderStroke(2.dp,
  1301. // colorResource(id = R.color.gray_icon))
  1302. )
  1303. {
  1304. Text(text = "Yes",
  1305. style = MaterialTheme.typography.labelLarge)
  1306. Log.d("test_button", "RowScope")
  1307. // val logoutResponse = accountViewModel.liveDataLogout.observeAsState().value
  1308. // if (logoutResponse == true) {
  1309. // accountViewModel.setLogoutStatus(false)
  1310. // Log.d("test_api_response","Logout live: $logoutResponse")
  1311. // basePreferenceHelper.setLoggedInState(false)
  1312. // settingsNavHostController.popBackStack()
  1313. // settingsNavHostController.navigate(Screen.Started.route)
  1314. // }
  1315. // else {
  1316. //// accountViewModel.setLogoutStatus(false)
  1317. //// onCancel()
  1318. // }
  1319. }
  1320. }
  1321. }
  1322. }
  1323. }
  1324. }
  1325. @OptIn(ExperimentalMaterial3Api::class)
  1326. @Composable
  1327. fun ColumnScope.ShowServerDialogTV(
  1328. prefHelper: BasePreferenceHelper,
  1329. wg: VPNConnectionsUtil
  1330. ) {
  1331. var isButtonFocused1 by remember { mutableStateOf(false) }
  1332. var isButtonFocused2 by remember { mutableStateOf(false) }
  1333. AlertDialog(
  1334. onDismissRequest = { isServerDialog.value = false },
  1335. properties = DialogProperties(),
  1336. modifier = Modifier
  1337. .fillMaxWidth()
  1338. .wrapContentHeight()
  1339. ) {
  1340. val lastServer = prefHelper.getConnectedServer()
  1341. val context = LocalContext.current
  1342. // val serverListViewModel: ServerListViewModel = viewModel {
  1343. // ServerListViewModel(context)
  1344. // }
  1345. Surface(
  1346. color = colorResource(id = R.color.white),
  1347. modifier = Modifier
  1348. .background(Color.Transparent)
  1349. .fillMaxWidth()
  1350. ,
  1351. shape = RoundedCornerShape(18.dp)
  1352. ) {
  1353. Column(
  1354. verticalArrangement = Arrangement.Top,
  1355. horizontalAlignment = Alignment.CenterHorizontally,
  1356. modifier = Modifier
  1357. .background(colorResource(id = R.color.white))
  1358. ) {
  1359. Log.d("islogoutClicked", "AlertDialog")
  1360. Text(text = "Confirm",
  1361. color = colorResource(id = R.color.dark_blue_gray_text),
  1362. style = MaterialTheme.typography.bodyMedium,
  1363. modifier = Modifier.padding(top = 45.dp)
  1364. )
  1365. Text(text = "Are you sure to switch from ${lastServer?.server_name} to ${serverObj.value.server_name}?",
  1366. color = colorResource(id = R.color.dark_blue_gray_text),
  1367. style = MaterialTheme.typography.labelSmall,
  1368. maxLines = 2,
  1369. modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 26.dp)
  1370. )
  1371. Row (
  1372. modifier = Modifier
  1373. .padding(top = 34.dp, bottom = 20.dp),
  1374. horizontalArrangement = Arrangement.SpaceBetween,
  1375. verticalAlignment = Alignment.Bottom
  1376. ) {
  1377. Button(
  1378. onClick = {
  1379. Log.d("test_button", "No")
  1380. isServerDialog.value = false
  1381. },
  1382. modifier = Modifier
  1383. .padding(
  1384. start = 15.dp, end = 5.dp,
  1385. bottom = 0.dp, top = 0.dp
  1386. )
  1387. .onFocusChanged {
  1388. isButtonFocused1 = it.isFocused
  1389. }
  1390. .background(colorResource(id = R.color.transparent))
  1391. .weight(1F)
  1392. .height(52.dp),
  1393. shape = RoundedCornerShape(15.dp),
  1394. colors = ButtonDefaults.buttonColors(
  1395. contentColor = if (isButtonFocused1) colorResource(id = R.color.dark_blue_gray_text) else colorResource(id = R.color.white),
  1396. containerColor = colorResource(id = R.color.light_blue),
  1397. ),
  1398. border = BorderStroke(2.dp, if (isButtonFocused1) colorResource(id = R.color.dark_blue_gray_text) else colorResource(id = R.color.light_blue))
  1399. )
  1400. {
  1401. Text(text = "No",
  1402. style = MaterialTheme.typography.labelLarge)
  1403. Log.d("test_button", "RowScope")
  1404. }
  1405. Button(
  1406. onClick = {
  1407. Log.d("test_button", "Yes")
  1408. isServerDialog.value = false
  1409. prefHelper.setServerObject(serverObj.value)
  1410. prefHelper.setConnectedServer(serverObj.value)
  1411. serverListViewModelSplash.setRecentlyConnectedServer(serverObj.value)
  1412. wg.stopVpn()
  1413. Handler().postDelayed(Runnable {
  1414. wg.startVpn()
  1415. }, 500)
  1416. Log.d("ServerCallbacks", "Yes click => ${isServerDialog.value}")
  1417. },
  1418. modifier = Modifier
  1419. .padding(
  1420. start = 5.dp, end = 15.dp,
  1421. bottom = 0.dp, top = 0.dp
  1422. )
  1423. .onFocusChanged {
  1424. isButtonFocused2 = it.isFocused
  1425. }
  1426. .background(colorResource(id = R.color.transparent))
  1427. .weight(1F)
  1428. .height(52.dp),
  1429. shape = RoundedCornerShape(15.dp),
  1430. colors = ButtonDefaults.buttonColors(
  1431. contentColor = if (isButtonFocused2) colorResource(id = R.color.dark_blue_gray_text) else colorResource(id = R.color.white),
  1432. containerColor = colorResource(id = R.color.red),
  1433. ),
  1434. border = BorderStroke(2.dp, if (isButtonFocused2) colorResource(id = R.color.dark_blue_gray_text) else colorResource(id = R.color.red))
  1435. )
  1436. {
  1437. Text(text = "Yes",
  1438. style = MaterialTheme.typography.labelLarge)
  1439. Log.d("test_button", "RowScope")
  1440. // val logoutResponse = accountViewModel.liveDataLogout.observeAsState().value
  1441. // if (logoutResponse == true) {
  1442. // accountViewModel.setLogoutStatus(false)
  1443. // Log.d("test_api_response","Logout live: $logoutResponse")
  1444. // basePreferenceHelper.setLoggedInState(false)
  1445. // settingsNavHostController.popBackStack()
  1446. // settingsNavHostController.navigate(Screen.Started.route)
  1447. // }
  1448. // else {
  1449. //// accountViewModel.setLogoutStatus(false)
  1450. //// onCancel()
  1451. // }
  1452. }
  1453. }
  1454. }
  1455. }
  1456. }
  1457. }
  1458. @Composable
  1459. fun BoxScope.AddRowSmartTV(
  1460. navHostController: NavHostController,
  1461. basePreferenceHelper: BasePreferenceHelper,
  1462. context: Context,
  1463. isTablet: Boolean,
  1464. focusRequester2: FocusRequester,
  1465. homeViewModel: HomeViewModel
  1466. ) {
  1467. val smart = basePreferenceHelper.getSmartServerObject()
  1468. val recommended = basePreferenceHelper.getRecommendedServerObject()
  1469. val recently = basePreferenceHelper.getConnectedServer()
  1470. val anySpecific = basePreferenceHelper.getSmartServerObject()
  1471. val ipInfo = basePreferenceHelper.getIpinfo()
  1472. val selectedSmartList = basePreferenceHelper.getSmartList()
  1473. var selectedServer = basePreferenceHelper.getRecommendedServerObject()
  1474. var selectedSmartServer = basePreferenceHelper.getSmartServerObject()
  1475. var isButtonFocused by remember { mutableStateOf(false) }
  1476. Log.d("smartLocationList", "Home:: server = ${selectedServer?.server_name}")
  1477. var icon = Utils.getDrawable(context, selectedServer?.iso)
  1478. when(selectedSmartList) {
  1479. smartConnect[0] -> {
  1480. icon = Utils.getDrawable(context, recommended?.iso)
  1481. selectedServer = recommended
  1482. selectedSmartServer = recommended
  1483. }
  1484. smartConnect[1] -> {
  1485. icon = Utils.getDrawable(context, recently?.iso ?: recommended?.iso)
  1486. selectedServer = recently ?: recommended
  1487. selectedSmartServer = recently
  1488. }
  1489. smartConnect[2] -> {
  1490. icon = Utils.getDrawable(context, anySpecific?.iso ?: recommended?.iso)
  1491. selectedServer = anySpecific ?: recommended
  1492. selectedSmartServer = anySpecific
  1493. }
  1494. else -> {}
  1495. }
  1496. Row(
  1497. modifier = Modifier
  1498. .fillMaxWidth()
  1499. .padding(horizontal = 15.dp, vertical = 5.dp)
  1500. .background(Color.Transparent),
  1501. horizontalArrangement = Arrangement.Start,
  1502. verticalAlignment = Alignment.CenterVertically
  1503. ) {
  1504. Surface(
  1505. modifier = Modifier.padding(start = 0.dp),
  1506. color = Color.Transparent
  1507. ) {
  1508. if (icon != 0) {
  1509. Icon(
  1510. painter = painterResource(id = icon),
  1511. contentDescription = "Country Logo",
  1512. tint = Color.Unspecified,
  1513. modifier = Modifier
  1514. .padding(start = 0.dp)
  1515. .size(30.dp)
  1516. .weight(1f)
  1517. .clip(CircleShape)
  1518. .border(1.dp, colorResource(id = R.color.gray_opac_04), CircleShape)
  1519. .paint(
  1520. painter = painterResource(id = icon),
  1521. contentScale = ContentScale.FillBounds
  1522. )
  1523. )
  1524. }
  1525. }
  1526. Column(
  1527. modifier = Modifier
  1528. .padding(start = 12.dp)
  1529. ) {
  1530. ColumnText(
  1531. text = selectedSmartList,
  1532. color = MaterialTheme.colorScheme.surfaceContainerLow,
  1533. // color = colorResource(id = R.color.blue_text),
  1534. size = 12.sp,
  1535. style = MaterialTheme.typography.customTypography.headlineSmall.copy(
  1536. fontSize = 16.sp
  1537. )
  1538. )
  1539. ColumnText(
  1540. text = "${selectedServer?.server_name}",
  1541. color = MaterialTheme.colorScheme.primary,
  1542. // color = colorResource(id = R.color.dark_blue_gray_text),
  1543. size = 16.sp,
  1544. style = MaterialTheme.typography.labelMedium.copy(
  1545. fontSize = 16.sp
  1546. )
  1547. )
  1548. }
  1549. Spacer(modifier = Modifier.weight(1F))
  1550. Surface(
  1551. modifier = Modifier
  1552. .padding(start = 15.dp),
  1553. color = Color.Transparent
  1554. ) {
  1555. var isConnect: Int? = homeViewModel.isConnect.observeAsState().value
  1556. isConnect = basePreferenceHelper.getConnectState()
  1557. val color = if (isButtonFocused && isConnect == App.CONNECTED) MaterialTheme.colorScheme.primary
  1558. else if (isButtonFocused) MaterialTheme.colorScheme.primary
  1559. else MaterialTheme.colorScheme.surfaceContainerLow
  1560. ClickableText(
  1561. modifier = Modifier
  1562. .onKeyEvent {
  1563. when (it.key) {
  1564. Key.DirectionLeft -> {
  1565. true
  1566. }
  1567. Key.DirectionRight -> {
  1568. true
  1569. }
  1570. else -> {
  1571. false
  1572. }
  1573. }
  1574. }
  1575. .focusRequester(focusRequester2)
  1576. .onFocusChanged {
  1577. isButtonFocused = it.isFocused
  1578. }
  1579. .clickable {
  1580. toChangeServer.value = true
  1581. navHostController.navigate(
  1582. ScreenTV.ServerListTV.route
  1583. )
  1584. }
  1585. .focusable(),
  1586. text = AnnotatedString("Change"),
  1587. style = MaterialTheme.typography.customTypography.headlineMedium.copy(
  1588. // color = MaterialTheme.colorScheme.surfaceContainerLow,
  1589. color = color,
  1590. fontSize = 18.sp
  1591. ),
  1592. onClick = {},
  1593. )
  1594. }
  1595. }
  1596. }
  1597. @Composable
  1598. fun BoxScope.AddRowSelectServerTV(navHostController: NavHostController, isTablet: Boolean) {
  1599. val context = LocalContext.current
  1600. Row(
  1601. modifier = Modifier
  1602. .fillMaxWidth()
  1603. .padding(horizontal = 15.dp)
  1604. .background(Color.Transparent)
  1605. // .pointerInput(Unit) {
  1606. // detectTapGestures {
  1607. // toChangeServer.value = false
  1608. // navHostController.navigate(
  1609. // Screen.ServerList.route
  1610. // )
  1611. // Screen.ServerList.isTrue = true
  1612. // Log.d("button_click_change", "Pressed")
  1613. // }
  1614. // }
  1615. ,
  1616. horizontalArrangement = Arrangement.Start,
  1617. verticalAlignment = Alignment.CenterVertically
  1618. ) {
  1619. Surface(
  1620. modifier = Modifier.padding(start = 0.dp),
  1621. color = Color.Transparent
  1622. ) {
  1623. Image(
  1624. painter = painterResource(id = R.drawable.worldmap3x),
  1625. contentDescription = "World",
  1626. modifier = Modifier
  1627. .padding(start = 0.dp)
  1628. .size(30.dp)
  1629. .weight(1f)
  1630. )
  1631. }
  1632. Surface(
  1633. modifier = Modifier.padding(start = 0.dp),
  1634. color = Color.Transparent
  1635. ) {
  1636. Text(text = "See All Locations",
  1637. style = MaterialTheme.typography.labelMedium.copy(
  1638. fontSize = if (isTablet()) 20.sp else 16.sp
  1639. ),
  1640. color = MaterialTheme.colorScheme.primary,
  1641. // color = colorResource(id = R.color.dark_blue_gray_text),
  1642. maxLines = 2,
  1643. modifier = Modifier
  1644. .padding(start = 12.dp, end = 0.dp)
  1645. .weight(1f)
  1646. )
  1647. }
  1648. Spacer(modifier = Modifier.weight(1F))
  1649. Surface(
  1650. modifier = Modifier.padding(start = 15.dp),
  1651. color = Color.Transparent
  1652. ) {
  1653. Image(
  1654. painter = painterResource(id = R.drawable.frontarrow3x),
  1655. contentDescription = "Front_Arrow",
  1656. colorFilter = ColorFilter.tint(colorResource(id = R.color.dark_blue_gray_text)),
  1657. modifier = Modifier
  1658. .padding(start = 0.dp, end = 5.dp)
  1659. .size(10.dp, 18.dp)
  1660. .weight(1f)
  1661. )
  1662. }
  1663. }
  1664. }
  1665. @Composable
  1666. fun ColumnScope.AddText(
  1667. text: String,
  1668. size: TextUnit,
  1669. color: Color,
  1670. style: TextStyle
  1671. ) {
  1672. Text(
  1673. text = text,
  1674. style = style,
  1675. color = color,
  1676. modifier = Modifier.padding(top = 5.dp)
  1677. )
  1678. }
  1679. @Composable
  1680. fun ColumnScope.ColumnText(
  1681. text: String,
  1682. color: Color,
  1683. size: TextUnit,
  1684. style: TextStyle
  1685. ) {
  1686. Surface(
  1687. modifier = Modifier.padding(start = 0.dp),
  1688. color = Color.Transparent
  1689. ) {
  1690. Text(text = text,
  1691. style = style,
  1692. color = color,
  1693. maxLines = 1,
  1694. modifier = Modifier
  1695. .padding(start = 0.dp, end = 0.dp)
  1696. .weight(1f)
  1697. )
  1698. }
  1699. }
  1700. @Composable
  1701. fun RowScope.AddText(
  1702. text: String,
  1703. size: TextUnit,
  1704. color: Color,
  1705. isTablet: Boolean
  1706. ) {
  1707. Text(
  1708. text = text,
  1709. style = MaterialTheme.typography.labelMedium.copy(
  1710. fontSize = 18.sp
  1711. ),
  1712. color = color,
  1713. modifier = Modifier.padding(top = 0.dp)
  1714. )
  1715. }
  1716. @Composable
  1717. fun OnLifecycleEvent(onEvent: (
  1718. owner: LifecycleOwner,
  1719. event: Lifecycle.Event
  1720. ) -> Unit) {
  1721. val eventHandler = rememberUpdatedState(onEvent)
  1722. val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
  1723. DisposableEffect(lifecycleOwner.value) {
  1724. val lifecycle = lifecycleOwner.value.lifecycle
  1725. val observer = LifecycleEventObserver { owner, event ->
  1726. eventHandler.value(owner, event)
  1727. }
  1728. lifecycle.addObserver(observer)
  1729. onDispose {
  1730. lifecycle.removeObserver(observer)
  1731. }
  1732. }
  1733. }
  1734. private fun getEnableProtocols(protocol_name: String, prefHelper: BasePreferenceHelper): Boolean {
  1735. prefHelper.getEnabledProtocols().let {
  1736. if (it.contains(protocol_name)) {
  1737. return true
  1738. }
  1739. }
  1740. return false
  1741. }
  1742. @Composable
  1743. fun pinkBackgroundTV(): Painter {
  1744. return if (isDarkTheme.value) painterResource(id = R.drawable.darkpinkbackground)
  1745. else painterResource(id = R.drawable.pinkbackground3x)
  1746. }
  1747. @Composable
  1748. fun blueBackgroundTV(): Painter {
  1749. return if (isDarkTheme.value) painterResource(id = R.drawable.darkbluebackground)
  1750. else painterResource(id = R.drawable.bluebackground3x)
  1751. }