CountryItem.kt 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. package com.vpn.fastestvpnservice.customItems
  2. import android.util.Log
  3. import android.widget.Toast
  4. import androidx.compose.foundation.background
  5. import androidx.compose.foundation.border
  6. import androidx.compose.foundation.clickable
  7. import androidx.compose.foundation.interaction.MutableInteractionSource
  8. import androidx.compose.foundation.layout.Arrangement
  9. import androidx.compose.foundation.layout.Box
  10. import androidx.compose.foundation.layout.Column
  11. import androidx.compose.foundation.layout.ColumnScope
  12. import androidx.compose.foundation.layout.Row
  13. import androidx.compose.foundation.layout.Spacer
  14. import androidx.compose.foundation.layout.fillMaxWidth
  15. import androidx.compose.foundation.layout.height
  16. import androidx.compose.foundation.layout.padding
  17. import androidx.compose.foundation.layout.size
  18. import androidx.compose.foundation.shape.CircleShape
  19. import androidx.compose.material3.Icon
  20. import androidx.compose.material3.IconButton
  21. import androidx.compose.material3.MaterialTheme
  22. import androidx.compose.material3.Surface
  23. import androidx.compose.material3.Text
  24. import androidx.compose.runtime.Composable
  25. import androidx.compose.runtime.LaunchedEffect
  26. import androidx.compose.runtime.MutableState
  27. import androidx.compose.runtime.getValue
  28. import androidx.compose.runtime.livedata.observeAsState
  29. import androidx.compose.runtime.mutableIntStateOf
  30. import androidx.compose.runtime.mutableStateOf
  31. import androidx.compose.runtime.remember
  32. import androidx.compose.runtime.rememberCoroutineScope
  33. import androidx.compose.runtime.saveable.rememberSaveable
  34. import androidx.compose.runtime.setValue
  35. import androidx.compose.ui.Alignment
  36. import androidx.compose.ui.Modifier
  37. import androidx.compose.ui.draw.alpha
  38. import androidx.compose.ui.draw.clip
  39. import androidx.compose.ui.draw.paint
  40. import androidx.compose.ui.graphics.Color
  41. import androidx.compose.ui.layout.ContentScale
  42. import androidx.compose.ui.platform.LocalContext
  43. import androidx.compose.ui.res.colorResource
  44. import androidx.compose.ui.res.painterResource
  45. import androidx.compose.ui.text.style.TextOverflow
  46. import androidx.compose.ui.tooling.preview.Preview
  47. import androidx.compose.ui.unit.dp
  48. import androidx.lifecycle.viewmodel.compose.viewModel
  49. import androidx.navigation.NavHostController
  50. import androidx.navigation.compose.rememberNavController
  51. import com.stealthcopter.networktools.Ping
  52. import com.stealthcopter.networktools.ping.PingResult
  53. import com.stealthcopter.networktools.ping.PingStats
  54. import com.vpn.fastestvpnservice.R
  55. import com.vpn.fastestvpnservice.beans.Server
  56. import com.vpn.fastestvpnservice.beans.favListServer
  57. import com.vpn.fastestvpnservice.beans.toChangeServer
  58. import com.vpn.fastestvpnservice.constants.smartConnect
  59. import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
  60. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.onServer
  61. import com.vpn.fastestvpnservice.screens.serverListViewModelSplash
  62. import com.vpn.fastestvpnservice.sealedClass.Screen
  63. import com.vpn.fastestvpnservice.utils.Utils
  64. import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
  65. import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
  66. import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
  67. var serverInfoObj: MutableState<Server> = mutableStateOf(Server())
  68. @Composable
  69. fun CountryItem(
  70. server: Server,
  71. category: String,
  72. countryTotalServers: Int,
  73. navHostController: NavHostController,
  74. index: Int
  75. ) {
  76. Box(
  77. modifier = Modifier
  78. .fillMaxWidth()
  79. .background(
  80. color = MaterialTheme.colorScheme.background
  81. )
  82. .padding(bottom = 1.dp)
  83. ) {
  84. val context = LocalContext.current
  85. val basePreferenceHelper = BasePreferenceHelper(context)
  86. val countrySize by rememberSaveable { mutableStateOf(server.totalServers) }
  87. var isServerExpanded by rememberSaveable { mutableStateOf(false) }
  88. // val serverListViewModel: ServerListViewModel = viewModel{
  89. // ServerListViewModel(context)
  90. // }
  91. // val splashViewModel: SplashViewModel = viewModel{
  92. // SplashViewModel(context)
  93. // }
  94. val scope = rememberCoroutineScope()
  95. val homeViewModel: HomeViewModel = viewModel {
  96. HomeViewModel(context, scope)
  97. }
  98. var isCountryServerClicked by remember { mutableStateOf(false) }
  99. if (isCountryServerClicked) {
  100. Log.d("ServerCallbacks", "isServerClicked $isCountryServerClicked")
  101. onServer.onServerSelected(context, homeViewModel,
  102. onClick = { isCountryServerClicked = false },
  103. true,
  104. server
  105. )
  106. navHostController.popBackStack()
  107. }
  108. var isServerServerClicked by remember { mutableStateOf(false) }
  109. if (isServerServerClicked) {
  110. Log.d("ServerCallbacks", "isServerClicked $isServerServerClicked")
  111. onServer.onServerSelected(
  112. context,
  113. homeViewModel,
  114. onClick = { isServerServerClicked = false },
  115. true,
  116. server
  117. )
  118. navHostController.popBackStack()
  119. }
  120. // countrySize.let { size -> }
  121. val icon = if (server.enable == 1) Utils.getDrawable(context, server.iso)
  122. else Utils.getDrawableGray(context, server.iso)
  123. Column {
  124. /* Country Location's Row */
  125. Box(
  126. // verticalAlignment = Alignment.Top,
  127. // horizontalArrangement = Arrangement.Start,
  128. modifier = Modifier
  129. .fillMaxWidth()
  130. .padding(
  131. start = 12.dp, end = 7.dp, top = 12.dp
  132. )
  133. .background(Color.Transparent)
  134. .clickable(
  135. indication = null,
  136. interactionSource = remember { MutableInteractionSource() }
  137. ) {
  138. isServerExpanded = !isServerExpanded
  139. // Toast.makeText(context, index.toString(), Toast.LENGTH_SHORT).show()
  140. // commenting, open server list, not connecting by tap on tab
  141. // if (server.enable == 1) {
  142. //// basePreferenceHelper.setServerObject(server)
  143. // isCountryServerClicked = true
  144. // } else {
  145. // basePreferenceHelper.setSubscriptionServerObject(server)
  146. // Screen.Subscription.isTrue = true
  147. // navHostController.navigate(
  148. // Screen.Subscription.route
  149. // )
  150. // }
  151. }
  152. ) {
  153. // val icon = if (server.enable == 1) Utils.getDrawable(context, server.iso)
  154. // else Utils.getDrawableGray(context, server.iso)
  155. Log.d("test_server_flag", "${server.country} $icon")
  156. if (icon != 0) {
  157. Icon(
  158. painter = painterResource(id = icon),
  159. contentDescription = "Server Logo",
  160. tint = Color.Unspecified,
  161. modifier = Modifier
  162. .padding(bottom = 15.dp)
  163. .size(24.dp)
  164. .clip(CircleShape)
  165. .border(1.dp, colorResource(id = R.color.gray_opac_04), CircleShape)
  166. .paint(
  167. painter = painterResource(id = icon),
  168. contentScale = ContentScale.FillBounds
  169. )
  170. .align(Alignment.CenterStart)
  171. )
  172. Surface(
  173. modifier = Modifier
  174. .padding(start = 40.dp, bottom = 15.dp, end = 110.dp)
  175. .align(Alignment.CenterStart)
  176. .background(Color.Transparent),
  177. color = Color.Transparent
  178. ) {
  179. Text(
  180. text = server.country!!,
  181. style = MaterialTheme.typography.labelMedium,
  182. color = MaterialTheme.colorScheme.primary,
  183. maxLines = 1,
  184. overflow = TextOverflow.Ellipsis,
  185. modifier = Modifier
  186. .align(Alignment.CenterStart)
  187. )
  188. }
  189. // Spacer(modifier = Modifier.weight(1F))
  190. Text(
  191. text = "$countryTotalServers ${context.getString(R.string.locations)}",
  192. style = MaterialTheme.typography.bodySmall,
  193. color = MaterialTheme.colorScheme.primary,
  194. modifier = Modifier
  195. .padding(end = 50.dp, bottom = 15.dp)
  196. .align(Alignment.CenterEnd)
  197. .alpha(0.4F)
  198. )
  199. // Spacer(modifier = Modifier.weight(1F))
  200. Icon(
  201. modifier = Modifier
  202. .padding(bottom = 15.dp, end = 4.dp)
  203. .size(12.dp, 7.dp)
  204. .align(Alignment.CenterEnd)
  205. .clickable(
  206. indication = null,
  207. interactionSource = remember { MutableInteractionSource() }
  208. ) { isServerExpanded = !isServerExpanded },
  209. painter = if (isServerExpanded) painterResource(
  210. id = R.drawable.dragarrow3x
  211. ) else painterResource(
  212. id = R.drawable.downarrow3x
  213. ),
  214. contentDescription = "Server Logo",
  215. tint = MaterialTheme.colorScheme.primary,
  216. )
  217. }
  218. }
  219. /* Country Expandable's Row */
  220. if (isServerExpanded) {
  221. // val countriesServersData1 = basePreferenceHelper.getServerData().get(0).servers
  222. // countriesServersData1?.let {
  223. //// serverListViewModelSplash.getServerGroupList(server, it)
  224. // }
  225. val serversGroup = serverListViewModelSplash.liveDataGroupServers.observeAsState().value
  226. serversGroup?.get(index)?.servers?.let { it1 -> ExpandableRow(server = it1, navHostController) }
  227. }
  228. }
  229. if (icon != 0) {
  230. Surface(
  231. modifier = Modifier
  232. .padding(start = 0.dp, end = 0.dp)
  233. .height(1.dp)
  234. .fillMaxWidth()
  235. .alpha(0.6F)
  236. .align(Alignment.BottomCenter),
  237. color = colorResource(id = R.color.gray_icon)
  238. ) {}
  239. }
  240. }
  241. }
  242. @Composable
  243. fun ColumnScope.ExpandableRow(
  244. server: ArrayList<Server>,
  245. navHostController: NavHostController
  246. ) {
  247. val context = LocalContext.current
  248. val basePreferenceHelper = BasePreferenceHelper(context)
  249. // val serverListViewModel: ServerListViewModel = viewModel{
  250. // ServerListViewModel(context)
  251. // }
  252. // val splashViewModel: SplashViewModel = viewModel{ SplashViewModel(context) }
  253. val scope = rememberCoroutineScope()
  254. val homeViewModel: HomeViewModel = viewModel { HomeViewModel(context, scope) }
  255. var isExpServerClicked by remember { mutableStateOf(false) }
  256. Column(
  257. modifier = Modifier
  258. .padding(
  259. start = 40.dp, end = 26.dp,
  260. top = 2.dp, bottom = 28.dp
  261. )
  262. .background(Color.Transparent)
  263. ) {
  264. // Expandable Row
  265. server.let { serverData ->
  266. serverData.forEachIndexed { index, serverInfo ->
  267. // Log.d("serverInfo_ping", "serverInfo ${serverInfo.server_name} :: ${serverInfo.ping}")
  268. var isFavorite by rememberSaveable { mutableStateOf(serverInfo.isFavourited) }
  269. val isServerFavourited: Boolean = serverInfo.isFavourited == true
  270. Log.d("test-server_fav_d", "${serverInfo.server_name} ${serverInfo.ping} $isFavorite")
  271. if (isExpServerClicked) {
  272. onServer.onServerSelected(
  273. context,
  274. homeViewModel,
  275. onClick = {isExpServerClicked = false},
  276. true,
  277. serverInfoObj.value
  278. )
  279. navHostController.popBackStack()
  280. }
  281. // var ping by rememberSaveable { mutableIntStateOf(0) }
  282. //
  283. // fun updatePing(newPing: Int) {
  284. // ping = newPing
  285. // }
  286. //
  287. // LaunchedEffect(key1 = Unit) {
  288. // Log.d("test_new_ping", "Inside LE")
  289. //// while (true) {
  290. // Ping.onAddress(serverInfo.ip as String).setTimeOutMillis(1000).doPing(
  291. // object : Ping.PingListener{
  292. // override fun onResult(pingResult: PingResult?) {
  293. // pingResult?.let {
  294. // Log.d("test_new_ping", "pingResult = ${it.timeTaken.toInt()}")
  295. // if (ping == 0) updatePing(it.timeTaken.toInt())
  296. // }
  297. // }
  298. // override fun onError(e: Exception?) {}
  299. // override fun onFinished(pingStats: PingStats?) {}
  300. // }
  301. // )
  302. //// delay(3 * 1000)
  303. //// }
  304. // }
  305. Row(
  306. verticalAlignment = Alignment.CenterVertically,
  307. horizontalArrangement = Arrangement.Start,
  308. modifier = Modifier
  309. .fillMaxWidth()
  310. .padding(
  311. vertical = 15.dp
  312. )
  313. .background(Color.Transparent)
  314. .clickable(
  315. indication = null,
  316. interactionSource = remember { MutableInteractionSource() }
  317. ) {
  318. if (serverInfo.enable == 1) {
  319. if (toChangeServer.value) {
  320. Log.d("test_change_Server", "true-Change")
  321. basePreferenceHelper.saveSmartList(smartConnect[2])
  322. basePreferenceHelper.setSmartServerObject(serverInfo)
  323. navHostController.popBackStack()
  324. } else {
  325. Log.d("test_change_Server", "false : Connect")
  326. serverInfoObj.value = serverInfo
  327. // basePreferenceHelper.setServerObject(serverInfo)
  328. isExpServerClicked = true
  329. }
  330. } else {
  331. basePreferenceHelper.setSubscriptionServerObject(serverInfo)
  332. Screen.Subscription.isTrue = true
  333. navHostController.navigate(
  334. Screen.Subscription.route
  335. )
  336. }
  337. }
  338. ) {
  339. Text(text = "${serverInfo.server_name}",
  340. style = MaterialTheme.typography.labelMedium,
  341. color = MaterialTheme.colorScheme.onSecondary,
  342. modifier = Modifier
  343. .padding(start = 16.dp, bottom = 0.dp)
  344. .align(Alignment.CenterVertically)
  345. .alpha(0.4F)
  346. )
  347. Spacer(modifier = Modifier.weight(1F))
  348. Text(text = "${serverInfo.ping} ms",
  349. style = MaterialTheme.typography.displayMedium,
  350. color = colorResource(id = R.color.blue_text),
  351. modifier = Modifier
  352. .padding(start = 0.dp, end = 30.dp)
  353. .align(Alignment.CenterVertically)
  354. )
  355. IconButton(
  356. modifier = Modifier
  357. .padding(bottom = 0.dp, end = 16.dp)
  358. .size(25.dp)
  359. .align(Alignment.CenterVertically),
  360. onClick = {
  361. isFavorite = !isFavorite!!
  362. serverListViewModelSplash.favAndUnFav(serverInfo)
  363. }
  364. )
  365. {
  366. Icon(
  367. painter = if (isServerFavourited) painterResource(
  368. id = R.drawable.fav_server3x) else painterResource(
  369. id = R.drawable.unfav_server3x),
  370. contentDescription = "Server Logo",
  371. tint = Color.Unspecified,
  372. modifier = Modifier.size(22.dp, 21.dp)
  373. )
  374. }
  375. }
  376. Surface(
  377. modifier = Modifier
  378. .padding(top = 0.dp, end = 0.dp)
  379. .height(1.dp)
  380. .fillMaxWidth()
  381. .alpha(0.6F),
  382. color = colorResource(id = R.color.gray_icon)
  383. ) {}
  384. }
  385. }
  386. }
  387. }
  388. @Preview
  389. @Composable
  390. fun CountryItemPreview() {
  391. CountryItem(server = favListServer[0], "servers", 1, rememberNavController(), 0)
  392. }