HomeScreenTV.kt 84 KB

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