ServerItem.kt 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. package com.vpn.fastestvpnservice.customItems
  2. import android.content.res.Configuration
  3. import android.os.Looper
  4. import android.util.Log
  5. import android.widget.Toast
  6. import androidx.compose.foundation.BorderStroke
  7. import androidx.compose.foundation.Image
  8. import androidx.compose.foundation.background
  9. import androidx.compose.foundation.border
  10. import androidx.compose.foundation.clickable
  11. import androidx.compose.foundation.interaction.MutableInteractionSource
  12. import androidx.compose.foundation.layout.Arrangement
  13. import androidx.compose.foundation.layout.Box
  14. import androidx.compose.foundation.layout.Row
  15. import androidx.compose.foundation.layout.Spacer
  16. import androidx.compose.foundation.layout.fillMaxWidth
  17. import androidx.compose.foundation.layout.height
  18. import androidx.compose.foundation.layout.padding
  19. import androidx.compose.foundation.layout.size
  20. import androidx.compose.foundation.shape.CircleShape
  21. import androidx.compose.foundation.shape.RoundedCornerShape
  22. import androidx.compose.material3.Icon
  23. import androidx.compose.material3.IconButton
  24. import androidx.compose.material3.MaterialTheme
  25. import androidx.compose.material3.Surface
  26. import androidx.compose.material3.Text
  27. import androidx.compose.runtime.Composable
  28. import androidx.compose.runtime.getValue
  29. import androidx.compose.runtime.livedata.observeAsState
  30. import androidx.compose.runtime.mutableIntStateOf
  31. import androidx.compose.runtime.mutableStateOf
  32. import androidx.compose.runtime.remember
  33. import androidx.compose.runtime.rememberCoroutineScope
  34. import androidx.compose.runtime.saveable.rememberSaveable
  35. import androidx.compose.runtime.setValue
  36. import androidx.compose.ui.Alignment
  37. import androidx.compose.ui.Modifier
  38. import androidx.compose.ui.draw.alpha
  39. import androidx.compose.ui.draw.clip
  40. import androidx.compose.ui.draw.paint
  41. import androidx.compose.ui.graphics.Brush
  42. import androidx.compose.ui.graphics.Color
  43. import androidx.compose.ui.graphics.Shape
  44. import androidx.compose.ui.layout.ContentScale
  45. import androidx.compose.ui.platform.LocalContext
  46. import androidx.compose.ui.res.colorResource
  47. import androidx.compose.ui.res.painterResource
  48. import androidx.compose.ui.text.TextStyle
  49. import androidx.compose.ui.tooling.preview.Preview
  50. import androidx.compose.ui.unit.dp
  51. import androidx.compose.ui.unit.sp
  52. import androidx.lifecycle.viewmodel.compose.viewModel
  53. import androidx.navigation.NavHostController
  54. import androidx.navigation.compose.rememberNavController
  55. import com.stealthcopter.networktools.Ping
  56. import com.stealthcopter.networktools.ping.PingResult
  57. import com.stealthcopter.networktools.ping.PingStats
  58. import com.vpn.fastestvpnservice.R
  59. import com.vpn.fastestvpnservice.beans.Server
  60. import com.vpn.fastestvpnservice.beans.ServerList
  61. import com.vpn.fastestvpnservice.beans.favList
  62. import com.vpn.fastestvpnservice.beans.favListServer
  63. import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
  64. import com.vpn.fastestvpnservice.helpers.UIHelper
  65. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.onServer
  66. import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
  67. import com.vpn.fastestvpnservice.utils.Utils
  68. import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
  69. import com.vpn.fastestvpnservice.viewmodels.SearchListViewModel
  70. import com.vpn.fastestvpnservice.viewmodels.ServerListViewModel
  71. import com.vpn.fastestvpnservice.viewmodels.SplashViewModel
  72. import java.lang.Exception
  73. @Composable
  74. fun ServerItem(server: Server, navHostController: NavHostController) {
  75. val context = LocalContext.current
  76. val scope = rememberCoroutineScope()
  77. var isServerClicked by remember { mutableStateOf(false) }
  78. val homeViewModel: HomeViewModel = viewModel{ HomeViewModel(context, scope) }
  79. val basePreferenceHelper = BasePreferenceHelper(context)
  80. var isFavorite by remember { mutableStateOf(server.isFavourited) }
  81. val isServerFavourited: Boolean = server.isFavourited == true
  82. Log.d("test-server_fav_d", "$isFavorite")
  83. Box(
  84. modifier = Modifier
  85. .fillMaxWidth()
  86. .background(color = MaterialTheme.colorScheme.background)
  87. .padding(bottom = 1.dp)
  88. ) {
  89. val serverListViewModel: ServerListViewModel = viewModel{
  90. ServerListViewModel(context)
  91. }
  92. val splashViewModel: SplashViewModel = viewModel{
  93. SplashViewModel(context)
  94. }
  95. if (isServerClicked) {
  96. Log.d("ServerCallbacks", "isServerClicked $isServerClicked")
  97. onServer.onServerSelected(
  98. context,
  99. homeViewModel,
  100. onClick = { isServerClicked = false },
  101. false,
  102. server
  103. )
  104. navHostController.popBackStack()
  105. }
  106. Row(
  107. verticalAlignment = Alignment.Top,
  108. horizontalArrangement = Arrangement.Start,
  109. modifier = Modifier
  110. .fillMaxWidth()
  111. .padding(start = 12.dp, end = 7.dp, top = 12.dp)
  112. .clickable(
  113. indication = null,
  114. interactionSource = remember { MutableInteractionSource() }
  115. ) {
  116. basePreferenceHelper.setServerObject(server)
  117. isServerClicked = true
  118. }
  119. ) {
  120. var ping by remember { mutableIntStateOf(0) }
  121. // Ping.onAddress(server.ip as String).setTimeOutMillis(1000).doPing(
  122. // object : Ping.PingListener{
  123. // override fun onResult(pingResult: PingResult?) {
  124. // android.os.Handler(Looper.getMainLooper()).post {
  125. // ping = pingResult?.timeTaken?.toInt()!!
  126. // }
  127. // }
  128. //
  129. // override fun onError(e: Exception?) {}
  130. // override fun onFinished(pingStats: PingStats?) {}
  131. // }
  132. // )
  133. val icon = if (server.enable == 1) Utils.getDrawable(context, server.iso)
  134. else Utils.getDrawableGray(context, server.iso)
  135. Icon(
  136. painter = painterResource(id = icon),
  137. contentDescription = "Server Logo",
  138. tint = Color.Unspecified,
  139. modifier = Modifier
  140. .padding(bottom = 16.dp)
  141. .size(24.dp)
  142. .clip(CircleShape)
  143. .paint(
  144. painter = painterResource(id = icon),
  145. contentScale = ContentScale.FillHeight
  146. )
  147. )
  148. Text(text = server.server_name!!,
  149. style = MaterialTheme.typography.labelMedium,
  150. color = MaterialTheme.colorScheme.primary,
  151. modifier = Modifier
  152. .padding(start = 16.dp, bottom = 18.dp)
  153. .align(Alignment.CenterVertically)
  154. )
  155. Spacer(modifier = Modifier.weight(1F))
  156. Text(text = "${server.ping} ms",
  157. style = MaterialTheme.typography.displayMedium,
  158. color = colorResource(id = R.color.blue_text),
  159. modifier = Modifier
  160. .padding(end = 30.dp, bottom = 18.dp)
  161. .align(Alignment.CenterVertically)
  162. )
  163. // Spacer(modifier = Modifier.weight(1F))
  164. IconButton(
  165. modifier = Modifier
  166. .padding(bottom = 18.dp, end = 8.dp)
  167. .size(22.dp, 21.dp),
  168. onClick = {
  169. isFavorite = !isFavorite!!
  170. serverListViewModel.favAndUnFav(server)
  171. }
  172. ) {
  173. Icon(
  174. modifier = Modifier,
  175. painter = if (isServerFavourited) painterResource(
  176. id = R.drawable.fav_server3x) else painterResource(
  177. id = R.drawable.unfav_server3x),
  178. contentDescription = "Server Logo",
  179. tint = Color.Unspecified,
  180. )
  181. }
  182. }
  183. Surface(
  184. modifier = Modifier
  185. .padding(start = 0.dp, end = 0.dp)
  186. .height(1.dp)
  187. .fillMaxWidth()
  188. .alpha(0.6F)
  189. .align(Alignment.BottomCenter),
  190. color = colorResource(id = R.color.gray_icon)
  191. ) {}
  192. }
  193. }
  194. @Composable
  195. fun FavoriteServerItem(server: Server, navHostController: NavHostController) {
  196. val context = LocalContext.current
  197. val basePreferenceHelper = BasePreferenceHelper(context)
  198. var serverListViewModel: ServerListViewModel = viewModel {
  199. ServerListViewModel(context = context)
  200. }
  201. val splashViewModel: SplashViewModel = viewModel{
  202. SplashViewModel(context)
  203. }
  204. val scope = rememberCoroutineScope()
  205. val homeViewModel: HomeViewModel = viewModel {
  206. HomeViewModel(context, scope)
  207. }
  208. var isFavorite by remember { mutableStateOf(server.isFavourited) }
  209. val isServerFavourited: Boolean = server.isFavourited == true
  210. Log.d("test-server_fav_d", "$isFavorite")
  211. var isFavServerClicked by remember { mutableStateOf(false) }
  212. if (isFavServerClicked) {
  213. Log.d("ServerCallbacks", "isServerClicked $isFavServerClicked")
  214. onServer.onServerSelected(
  215. context,
  216. homeViewModel,
  217. onClick = { isFavServerClicked = false },
  218. true,
  219. server
  220. )
  221. navHostController.popBackStack(BottomBarScreen.Home.route, false)
  222. }
  223. Box(
  224. modifier = Modifier
  225. .fillMaxWidth()
  226. .background(MaterialTheme.colorScheme.background)
  227. .padding(bottom = 1.dp)
  228. ) {
  229. Row(
  230. verticalAlignment = Alignment.Top,
  231. horizontalArrangement = Arrangement.Start,
  232. modifier = Modifier
  233. .fillMaxWidth()
  234. .padding(start = 12.dp, end = 7.dp, top = 12.dp)
  235. .clickable(
  236. indication = null,
  237. interactionSource = remember { MutableInteractionSource() }
  238. ) {
  239. // Toast
  240. // .makeText(
  241. // context, server.server_name, Toast.LENGTH_SHORT
  242. // )
  243. // .show()
  244. // basePreferenceHelper.setServerObject(server)
  245. isFavServerClicked = true
  246. // navHostController.popBackStack()
  247. }
  248. ) {
  249. var ping by remember { mutableIntStateOf(0) }
  250. // Ping.onAddress(server.ip as String).setTimeOutMillis(1000).doPing(
  251. // object : Ping.PingListener{
  252. // override fun onResult(pingResult: PingResult?) {
  253. // android.os.Handler(Looper.getMainLooper()).post {
  254. // ping = pingResult?.timeTaken?.toInt()!!
  255. // }
  256. // }
  257. //
  258. // override fun onError(e: Exception?) {}
  259. // override fun onFinished(pingStats: PingStats?) {}
  260. // }
  261. // )
  262. val icon = if (server.enable == 1) Utils.getDrawable(context, server.iso)
  263. else Utils.getDrawableGray(context, server.iso)
  264. Icon(
  265. painter = painterResource(id = icon),
  266. contentDescription = "Server Logo",
  267. tint = Color.Unspecified,
  268. modifier = Modifier
  269. .padding(bottom = 16.dp)
  270. .size(24.dp)
  271. .clip(CircleShape)
  272. .paint(
  273. painter = painterResource(id = icon),
  274. contentScale = ContentScale.FillHeight
  275. )
  276. )
  277. Text(text = server.server_name!!,
  278. color = MaterialTheme.colorScheme.primary,
  279. style = MaterialTheme.typography.labelMedium,
  280. modifier = Modifier
  281. .padding(start = 16.dp, bottom = 18.dp)
  282. .align(Alignment.CenterVertically)
  283. )
  284. Spacer(modifier = Modifier.weight(1F))
  285. Text(text = "${server.ping} ms",
  286. color = colorResource(id = R.color.blue_text),
  287. style = MaterialTheme.typography.displayMedium,
  288. modifier = Modifier
  289. .padding(end = 30.dp, bottom = 18.dp)
  290. .align(Alignment.CenterVertically)
  291. )
  292. // Spacer(modifier = Modifier.weight(1F))
  293. IconButton(
  294. onClick = {
  295. isFavorite = !isFavorite!!
  296. serverListViewModel.favAndUnFav(server)
  297. },
  298. modifier = Modifier
  299. .padding(bottom = 18.dp, end = 0.dp)
  300. .size(22.dp, 21.dp)
  301. // .clickable(
  302. // indication = null,
  303. // interactionSource = remember { MutableInteractionSource() }
  304. // ) { },
  305. ) {
  306. // val favResponse = serverListViewModel.mutableLiveDataFavUnFav.observeAsState().value
  307. // favResponse?.let {
  308. // Log.d("test_fav_response", it.message.toString())
  309. // splashViewModel.serverDataApi()
  310. // serverListViewModel.mutableLiveDataFavUnFav.value = null
  311. // }
  312. Icon(
  313. painter = if (isServerFavourited) painterResource(
  314. id = R.drawable.fav_server3x) else painterResource(
  315. id = R.drawable.unfav_server3x),
  316. contentDescription = "Server Logo",
  317. tint = Color.Unspecified,
  318. )
  319. }
  320. }
  321. Surface(
  322. modifier = Modifier
  323. .padding(start = 0.dp, end = 0.dp)
  324. .height(1.dp)
  325. .fillMaxWidth()
  326. .alpha(0.6F)
  327. .align(Alignment.BottomCenter)
  328. ,
  329. color = colorResource(id = R.color.gray_icon)
  330. ) {}
  331. }
  332. }
  333. @Composable
  334. fun ServerSearchItem(
  335. server: Server,
  336. navHostController: NavHostController,
  337. bgColor: Color = Color.White,
  338. textColor: Color = colorResource(id = R.color.dark_blue_gray_text),
  339. isServerCallbackShown: Boolean = true,
  340. onServerDisable: () -> Unit
  341. ) {
  342. val context = LocalContext.current
  343. val scope = rememberCoroutineScope()
  344. val basePreferenceHelper = BasePreferenceHelper(context)
  345. val serverListViewModel: ServerListViewModel = viewModel {
  346. ServerListViewModel(context = context)
  347. }
  348. val splashViewModel: SplashViewModel = viewModel{
  349. SplashViewModel(context)
  350. }
  351. val searchListViewModel: SearchListViewModel = viewModel{
  352. SearchListViewModel(context, serverListViewModel, splashViewModel)
  353. }
  354. val homeViewModel: HomeViewModel = viewModel{
  355. HomeViewModel(context, scope)
  356. }
  357. var isSearchServerClicked by remember {
  358. mutableStateOf(false)
  359. }
  360. var isFavorite by remember { mutableStateOf(server.isFavourited) }
  361. val isServerFavourited: Boolean = server.isFavourited == true
  362. Log.d("test-server_fav_d", "$isFavorite")
  363. if (isSearchServerClicked) {
  364. Log.d("ServerCallbacks", "isServerClicked $isSearchServerClicked")
  365. onServer.onServerSelected(
  366. context,
  367. homeViewModel,
  368. onClick = { isSearchServerClicked = false },
  369. false,
  370. server
  371. )
  372. navHostController.popBackStack()
  373. }
  374. Box(
  375. modifier = Modifier
  376. .fillMaxWidth()
  377. .background(color = bgColor)
  378. .padding(bottom = 1.dp)
  379. ) {
  380. Row(
  381. verticalAlignment = Alignment.Top,
  382. horizontalArrangement = Arrangement.Start,
  383. modifier = Modifier
  384. .fillMaxWidth()
  385. .padding(start = 12.dp, end = 7.dp, top = 12.dp)
  386. .clickable(
  387. indication = null,
  388. interactionSource = remember { MutableInteractionSource() }
  389. ) {
  390. basePreferenceHelper.setServerObject(server)
  391. isSearchServerClicked = isServerCallbackShown
  392. if (!isServerCallbackShown) {
  393. onServerDisable()
  394. }
  395. }
  396. ) {
  397. var ping by remember { mutableIntStateOf(0) }
  398. // Ping.onAddress(server.ip as String).setTimeOutMillis(1000).doPing(
  399. // object : Ping.PingListener{
  400. // override fun onResult(pingResult: PingResult?) {
  401. // android.os.Handler(Looper.getMainLooper()).post {
  402. // ping = pingResult?.timeTaken?.toInt()!!
  403. // }
  404. // }
  405. //
  406. // override fun onError(e: Exception?) {}
  407. // override fun onFinished(pingStats: PingStats?) {}
  408. // }
  409. // )
  410. val icon = if (server.enable == 1) Utils.getDrawable(context, server.iso)
  411. else Utils.getDrawableGray(context, server.iso)
  412. Icon(
  413. painter = painterResource(id = icon),
  414. contentDescription = "Server Logo",
  415. tint = Color.Unspecified,
  416. modifier = Modifier
  417. .padding(bottom = 16.dp)
  418. .size(24.dp)
  419. .clip(CircleShape)
  420. .paint(
  421. painter = painterResource(id = icon),
  422. contentScale = ContentScale.FillHeight
  423. )
  424. )
  425. Text(text = server.server_name!!,
  426. color = textColor,
  427. style = MaterialTheme.typography.labelMedium,
  428. modifier = Modifier
  429. .padding(start = 16.dp, bottom = 18.dp)
  430. .align(Alignment.CenterVertically)
  431. )
  432. Spacer(modifier = Modifier.weight(1F))
  433. Text(text = "${server.ping} ms",
  434. color = colorResource(id = R.color.blue_text),
  435. style = MaterialTheme.typography.displayMedium,
  436. modifier = Modifier
  437. .padding(end = 30.dp, bottom = 18.dp)
  438. .align(Alignment.CenterVertically)
  439. )
  440. IconButton(
  441. modifier = Modifier
  442. .padding(bottom = 18.dp, end = 8.dp)
  443. .size(22.dp, 21.dp),
  444. onClick = {
  445. isFavorite = !isFavorite!!
  446. serverListViewModel.favAndUnFav(server)
  447. }) {
  448. Icon(
  449. painter = if (isServerFavourited) painterResource(
  450. id = R.drawable.fav_server3x) else painterResource(
  451. id = R.drawable.unfav_server3x),
  452. contentDescription = "Server Logo",
  453. tint = Color.Unspecified,
  454. )
  455. }
  456. }
  457. Surface(
  458. modifier = Modifier
  459. .padding(start = 0.dp, end = 0.dp)
  460. .height(1.dp)
  461. .fillMaxWidth()
  462. .alpha(0.6F)
  463. .align(Alignment.BottomCenter),
  464. color = colorResource(id = R.color.gray_icon)
  465. ) {}
  466. }
  467. }
  468. @Composable
  469. fun ServerSpecificItem(
  470. server: Server,
  471. navHostController: NavHostController,
  472. onServerDisable: () -> Unit
  473. ) {
  474. val context = LocalContext.current
  475. val scope = rememberCoroutineScope()
  476. val basePreferenceHelper = BasePreferenceHelper(context)
  477. val serverListViewModel: ServerListViewModel = viewModel {
  478. ServerListViewModel(context = context)
  479. }
  480. val splashViewModel: SplashViewModel = viewModel{
  481. SplashViewModel(context)
  482. }
  483. val searchListViewModel: SearchListViewModel = viewModel{
  484. SearchListViewModel(context, serverListViewModel, splashViewModel)
  485. }
  486. val homeViewModel: HomeViewModel = viewModel{
  487. HomeViewModel(context, scope)
  488. }
  489. var isSearchServerClicked by remember {
  490. mutableStateOf(false)
  491. }
  492. Box(
  493. modifier = Modifier
  494. .fillMaxWidth()
  495. .background(color = MaterialTheme.colorScheme.background)
  496. .padding(bottom = 1.dp)
  497. ) {
  498. Row(
  499. verticalAlignment = Alignment.Top,
  500. horizontalArrangement = Arrangement.Start,
  501. modifier = Modifier
  502. .fillMaxWidth()
  503. .padding(start = 12.dp, end = 7.dp, top = 12.dp)
  504. .clickable(
  505. indication = null,
  506. interactionSource = remember { MutableInteractionSource() }
  507. ) {
  508. basePreferenceHelper.setServerObject(server)
  509. onServerDisable()
  510. }
  511. ) {
  512. val icon = if (server.enable == 1) Utils.getDrawable(context, server.iso)
  513. else Utils.getDrawableGray(context, server.iso)
  514. Icon(
  515. painter = painterResource(id = icon),
  516. contentDescription = "Server Logo",
  517. tint = Color.Unspecified,
  518. modifier = Modifier
  519. .padding(bottom = 16.dp)
  520. .size(24.dp)
  521. .clip(CircleShape)
  522. .paint(
  523. painter = painterResource(id = icon),
  524. contentScale = ContentScale.FillHeight
  525. )
  526. )
  527. Text(text = server.server_name!!,
  528. color = MaterialTheme.colorScheme.primary,
  529. style = MaterialTheme.typography.labelMedium,
  530. modifier = Modifier
  531. .padding(start = 16.dp, bottom = 18.dp)
  532. .align(Alignment.CenterVertically)
  533. )
  534. }
  535. Surface(
  536. modifier = Modifier
  537. .padding(start = 0.dp, end = 0.dp)
  538. .height(1.dp)
  539. .fillMaxWidth()
  540. .alpha(0.6F)
  541. .align(Alignment.BottomCenter)
  542. ,
  543. color = colorResource(id = R.color.gray_icon)
  544. ) {}
  545. }
  546. }
  547. @Preview
  548. @Composable
  549. fun ServerItemPreview() {
  550. ServerItem(server = favListServer[0], rememberNavController())
  551. }
  552. @Preview
  553. @Composable
  554. fun FavoriteServerItemPreview() {
  555. FavoriteServerItem(server = favListServer[0], rememberNavController())
  556. }
  557. @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
  558. @Composable
  559. fun FavoriteServerItemPreviewDark() {
  560. FavoriteServerItem(server = favListServer[0], rememberNavController())
  561. }
  562. @Preview
  563. @Composable
  564. fun ServerSearchItemPreview() {
  565. ServerSearchItem(server = favListServer[0], rememberNavController()) {}
  566. }