SettingsScreenTV.kt 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. package com.vpn.fastestvpnservice.screensTV
  2. import android.app.Activity
  3. import android.content.Context
  4. import android.content.Intent
  5. import android.os.Build
  6. import android.os.Bundle
  7. import android.os.Handler
  8. import android.util.Log
  9. import androidx.compose.foundation.ExperimentalFoundationApi
  10. import androidx.compose.foundation.Image
  11. import androidx.compose.foundation.LocalOverscrollConfiguration
  12. import androidx.compose.foundation.background
  13. import androidx.compose.foundation.clickable
  14. import androidx.compose.foundation.gestures.detectTapGestures
  15. import androidx.compose.foundation.isSystemInDarkTheme
  16. import androidx.compose.foundation.layout.Arrangement
  17. import androidx.compose.foundation.layout.Box
  18. import androidx.compose.foundation.layout.Column
  19. import androidx.compose.foundation.layout.ColumnScope
  20. import androidx.compose.foundation.layout.Row
  21. import androidx.compose.foundation.layout.Spacer
  22. import androidx.compose.foundation.layout.fillMaxSize
  23. import androidx.compose.foundation.layout.fillMaxWidth
  24. import androidx.compose.foundation.layout.height
  25. import androidx.compose.foundation.layout.padding
  26. import androidx.compose.foundation.layout.size
  27. import androidx.compose.foundation.lazy.LazyColumn
  28. import androidx.compose.foundation.lazy.items
  29. import androidx.compose.foundation.rememberScrollState
  30. import androidx.compose.foundation.selection.selectable
  31. import androidx.compose.foundation.shape.RoundedCornerShape
  32. import androidx.compose.foundation.verticalScroll
  33. import androidx.compose.material3.DockedSearchBar
  34. import androidx.compose.material3.ExperimentalMaterial3Api
  35. import androidx.compose.material3.Icon
  36. import androidx.compose.material3.MaterialTheme
  37. import androidx.compose.material3.ModalBottomSheet
  38. import androidx.compose.material3.RadioButton
  39. import androidx.compose.material3.RadioButtonDefaults
  40. import androidx.compose.material3.SearchBarDefaults
  41. import androidx.compose.material3.Surface
  42. import androidx.compose.material3.Switch
  43. import androidx.compose.material3.SwitchDefaults
  44. import androidx.compose.material3.Text
  45. import androidx.compose.material3.TextFieldDefaults
  46. import androidx.compose.material3.rememberModalBottomSheetState
  47. import androidx.compose.runtime.Composable
  48. import androidx.compose.runtime.CompositionLocalProvider
  49. import androidx.compose.runtime.LaunchedEffect
  50. import androidx.compose.runtime.getValue
  51. import androidx.compose.runtime.livedata.observeAsState
  52. import androidx.compose.runtime.mutableStateOf
  53. import androidx.compose.runtime.remember
  54. import androidx.compose.runtime.rememberCoroutineScope
  55. import androidx.compose.runtime.setValue
  56. import androidx.compose.ui.Alignment
  57. import androidx.compose.ui.Modifier
  58. import androidx.compose.ui.draw.alpha
  59. import androidx.compose.ui.draw.clip
  60. import androidx.compose.ui.draw.scale
  61. import androidx.compose.ui.focus.FocusRequester
  62. import androidx.compose.ui.focus.focusRequester
  63. import androidx.compose.ui.focus.onFocusChanged
  64. import androidx.compose.ui.graphics.Color
  65. import androidx.compose.ui.graphics.ColorFilter
  66. import androidx.compose.ui.graphics.toArgb
  67. import androidx.compose.ui.graphics.vector.ImageVector
  68. import androidx.compose.ui.input.pointer.pointerInput
  69. import androidx.compose.ui.platform.LocalContext
  70. import androidx.compose.ui.platform.LocalSoftwareKeyboardController
  71. import androidx.compose.ui.platform.LocalView
  72. import androidx.compose.ui.res.colorResource
  73. import androidx.compose.ui.res.painterResource
  74. import androidx.compose.ui.text.TextStyle
  75. import androidx.compose.ui.unit.Dp
  76. import androidx.compose.ui.unit.TextUnit
  77. import androidx.compose.ui.unit.dp
  78. import androidx.compose.ui.unit.sp
  79. import androidx.core.content.ContextCompat
  80. import androidx.lifecycle.viewmodel.compose.viewModel
  81. import androidx.navigation.NavHostController
  82. import com.vpn.fastestvpnservice.R
  83. import com.vpn.fastestvpnservice.beans.isDarkTheme
  84. import com.vpn.fastestvpnservice.beans.themesList
  85. import com.vpn.fastestvpnservice.constants.smartConnect
  86. import com.vpn.fastestvpnservice.customItems.ServerSpecificItem
  87. import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
  88. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.AddTextSettings
  89. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.getAvailableProtocols
  90. import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.vpnConnectionsUtil
  91. import com.vpn.fastestvpnservice.screens.searchListViewModelSplash
  92. import com.vpn.fastestvpnservice.sealedClass.BottomBarScreen
  93. import com.vpn.fastestvpnservice.sealedClass.Screen
  94. import com.vpn.fastestvpnservice.utils.isTablet
  95. import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
  96. import de.blinkt.openvpn.core.App
  97. import kotlinx.coroutines.delay
  98. import kotlinx.coroutines.launch
  99. @OptIn(ExperimentalFoundationApi::class)
  100. @Composable
  101. fun SettingsTV(navHostController: NavHostController) {
  102. val context = LocalContext.current
  103. val focusRequester1 = remember { FocusRequester() }
  104. val focusRequester2 = remember { FocusRequester() }
  105. val focusRequester3 = remember { FocusRequester() }
  106. val focusRequester4 = remember { FocusRequester() }
  107. val focusRequester5 = remember { FocusRequester() }
  108. CompositionLocalProvider(
  109. LocalOverscrollConfiguration provides null
  110. ) {
  111. Box(
  112. modifier = Modifier
  113. // .background(MaterialTheme.colorScheme.background)
  114. .background(colorResource(id = R.color.background_color_gray))
  115. .fillMaxSize()
  116. .padding(vertical = 10.dp),
  117. ) {
  118. val view = LocalView.current
  119. val window = (view.context as Activity).window
  120. window.statusBarColor = Color.Transparent.toArgb()
  121. window.navigationBarColor = Color.Transparent.toArgb()
  122. LaunchedEffect(Unit) {
  123. focusRequester1.requestFocus()
  124. }
  125. Column(
  126. verticalArrangement = Arrangement.Top,
  127. horizontalAlignment = Alignment.Start,
  128. modifier = Modifier
  129. .padding(start = 16.dp, end = 0.dp)
  130. .fillMaxSize()
  131. .verticalScroll(rememberScrollState())
  132. .background(Color.Transparent)
  133. ) {
  134. // if (BottomBarScreen.Settings.isTrue) {
  135. // AddRowSettingsSmart(
  136. // icon = R.drawable.smart_connect3x,
  137. // text = "Smart Connect",
  138. // isRowShown = false,
  139. // isSheetShown = true,
  140. // navHostController
  141. // )
  142. // }
  143. Spacer(modifier = Modifier.height(50.dp))
  144. AddTextSettingsTV(
  145. text = "Settings",
  146. size = 28.sp,
  147. color = MaterialTheme.colorScheme.inversePrimary,
  148. style = MaterialTheme.typography.headlineLarge
  149. )
  150. Spacer(modifier = Modifier.height(22.dp))
  151. AddRowSettingsColumnTV(
  152. icon = R.drawable.vpn_protocols3x,
  153. text = "VPN Protocols",
  154. focusRequester1,
  155. focusRequester2
  156. )
  157. AddRowSettingsSmartTV(
  158. icon = R.drawable.smart_connect3x,
  159. text = "Smart Connect",
  160. isRowShown = true,
  161. isSheetShown = false,
  162. navHostController,
  163. focusRequester2,
  164. focusRequester3
  165. )
  166. AddRowSwitchTV(
  167. icon = R.drawable.adblock3x,
  168. text = "AdBlock",
  169. focusRequester3
  170. )
  171. AddRowSettingsTV(
  172. icon = R.drawable.kill_switch3x,
  173. text = "Kill Switch",
  174. topPadding = 40.dp,
  175. onClick = {
  176. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  177. gotoVPNSettingsTV(context)
  178. }
  179. }
  180. )
  181. AddRowSettingsTV(
  182. icon = R.drawable.split_tunneling3x,
  183. text = "Split Tunneling",
  184. onClick = { navHostController.navigate(Screen.SplitTunneling.route) }
  185. )
  186. AddRowSettingsTV(
  187. icon = R.drawable.notification3x,
  188. text = "Notifications",
  189. onClick = { navHostController.navigate(Screen.Notifications.route) }
  190. )
  191. // AddRowDarkLightThemeTV(
  192. // icon = Icons.Default.DarkMode,
  193. // text = "Theme")
  194. }
  195. }
  196. }
  197. }
  198. private fun gotoVPNSettingsTV(context: Context) {
  199. try {
  200. val intent = Intent("android.net.vpn.SETTINGS")
  201. intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
  202. ContextCompat.startActivity(context, intent, Bundle())
  203. } catch (e: Exception) {
  204. e.printStackTrace()
  205. }
  206. }
  207. @Composable
  208. fun ColumnScope.AddRowSettingsTV(
  209. icon: Int,
  210. text: String,
  211. topPadding: Dp = 40.dp,
  212. onClick: () -> Unit
  213. ) {
  214. var isRowFocused by remember { mutableStateOf(false) }
  215. Row(
  216. modifier = Modifier
  217. .fillMaxWidth()
  218. .padding(top = 5.dp, end = 27.dp)
  219. .clip(RoundedCornerShape(4.dp))
  220. .background(if (isRowFocused) Color.LightGray else Color.White)
  221. .onFocusChanged {
  222. isRowFocused = it.isFocused
  223. }
  224. .height(61.dp)
  225. .pointerInput(Unit) {
  226. detectTapGestures {
  227. onClick()
  228. }
  229. }
  230. .clickable {
  231. onClick()
  232. },
  233. horizontalArrangement = Arrangement.Start,
  234. verticalAlignment = Alignment.CenterVertically
  235. ) {
  236. Surface(
  237. modifier = Modifier.padding(start = 20.dp),
  238. color = Color.Transparent
  239. ) {
  240. Image(
  241. painter = painterResource(id = icon),
  242. contentDescription = "World",
  243. modifier = Modifier
  244. .padding(start = 0.dp)
  245. .size(24.dp)
  246. .weight(1f),
  247. colorFilter = ColorFilter.tint(
  248. MaterialTheme.colorScheme.inversePrimary) )
  249. }
  250. Surface(
  251. modifier = Modifier.padding(start = 0.dp),
  252. color = Color.Transparent
  253. ) {
  254. Text(text = text,
  255. style = MaterialTheme.typography.titleSmall,
  256. color = MaterialTheme.colorScheme.inversePrimary,
  257. maxLines = 1,
  258. modifier = Modifier
  259. .padding(start = 18.dp, end = 0.dp)
  260. .weight(1f)
  261. )
  262. }
  263. Spacer(modifier = Modifier.weight(1f))
  264. Surface(
  265. modifier = Modifier
  266. .padding(end = 20.dp)
  267. .align(Alignment.CenterVertically),
  268. color = Color.Transparent
  269. ) {
  270. Image(
  271. painter = painterResource(id = R.drawable.frontarrow3x),
  272. contentDescription = "Front_Arrow",
  273. modifier = Modifier
  274. .padding(start = 0.dp, end = 0.dp)
  275. .size(10.dp, 18.dp)
  276. .weight(1f),
  277. colorFilter = ColorFilter.tint(
  278. MaterialTheme.colorScheme.inversePrimary
  279. )
  280. )
  281. }
  282. }
  283. }
  284. @Composable
  285. fun ColumnScope.AddTextSettingsTV(
  286. text: String,
  287. size: TextUnit,
  288. color: Color,
  289. bottomPadding: Dp = 0.dp,
  290. startPadding: Dp = 0.dp,
  291. style: TextStyle
  292. ) {
  293. Text(
  294. text = text,
  295. style = style,
  296. color = color,
  297. modifier = Modifier.padding(bottom = bottomPadding, start = startPadding)
  298. )
  299. }
  300. @Composable
  301. fun ColumnScope.AddRowSwitchTV(icon: Int, text: String, focusRequester3: FocusRequester) {
  302. val context = LocalContext.current
  303. val basePreferenceHelper = BasePreferenceHelper(context)
  304. var isRowFocused by remember { mutableStateOf(false) }
  305. var isSwitch by remember { mutableStateOf(basePreferenceHelper.getAdBlockState()) }
  306. val scope = rememberCoroutineScope()
  307. val homeViewModel: HomeViewModel = viewModel{
  308. HomeViewModel(context, scope)
  309. }
  310. val isConnect: Int? = homeViewModel.isConnect.observeAsState().value
  311. Row(
  312. modifier = Modifier
  313. .fillMaxWidth()
  314. .padding(top = 5.dp, end = 27.dp)
  315. .clip(RoundedCornerShape(4.dp))
  316. .background(if (isRowFocused) Color.LightGray else Color.White)
  317. // .focusRequester(focusRequester3)
  318. .onFocusChanged {
  319. isRowFocused = it.isFocused
  320. }
  321. .clickable {
  322. isSwitch = !isSwitch
  323. basePreferenceHelper.saveAdBlockState(isSwitch)
  324. if (isConnect == App.CONNECTED || isConnect == App.CONNECTING) {
  325. Log.d("isConnect_State_vpn", "stopVPN")
  326. vpnConnectionsUtil.stopVpn()
  327. Handler().postDelayed(Runnable {
  328. vpnConnectionsUtil.startVpn()
  329. }, 500)
  330. }
  331. }
  332. .height(61.dp),
  333. horizontalArrangement = Arrangement.Start,
  334. verticalAlignment = Alignment.CenterVertically
  335. ) {
  336. Surface(
  337. modifier = Modifier.padding(start = 20.dp),
  338. color = Color.Transparent
  339. ) {
  340. Image(
  341. painter = painterResource(id = icon),
  342. contentDescription = "World",
  343. modifier = Modifier
  344. .padding(start = 0.dp)
  345. .size(24.dp)
  346. .weight(1f),
  347. colorFilter = ColorFilter.tint(
  348. MaterialTheme.colorScheme.inversePrimary) )
  349. }
  350. Surface(
  351. modifier = Modifier.padding(start = 0.dp),
  352. color = Color.Transparent
  353. ) {
  354. Text(text = text,
  355. style = MaterialTheme.typography.titleSmall,
  356. color = MaterialTheme.colorScheme.inversePrimary,
  357. maxLines = 1,
  358. modifier = Modifier
  359. .padding(start = 18.dp, end = 0.dp)
  360. .weight(1f)
  361. )
  362. }
  363. Spacer(modifier = Modifier.weight(1f))
  364. // val vpnConnectionsUtil = VPNConnectionsUtil(context, act, homeViewModel)
  365. Surface(
  366. modifier = Modifier
  367. .padding(start = 0.dp, end = 13.dp)
  368. .align(Alignment.CenterVertically),
  369. color = Color.Transparent
  370. ) {
  371. Switch(
  372. checked = isSwitch,
  373. onCheckedChange = {
  374. isSwitch = it
  375. basePreferenceHelper.saveAdBlockState(it)
  376. if (isConnect == App.CONNECTED || isConnect == App.CONNECTING) {
  377. Log.d("isConnect_State_vpn", "stopVPN")
  378. vpnConnectionsUtil.stopVpn()
  379. Handler().postDelayed(Runnable {
  380. vpnConnectionsUtil.startVpn()
  381. }, 500)
  382. } },
  383. modifier = Modifier.scale(0.8F),
  384. colors = SwitchDefaults.colors(
  385. checkedThumbColor = Color.White,
  386. // checkedTrackColor = MaterialTheme.colorScheme.surfaceContainerLowest,
  387. checkedTrackColor = colorResource(id = R.color.switch_green),
  388. // uncheckedThumbColor = MaterialTheme.colorScheme.onSecondaryContainer,
  389. uncheckedThumbColor = colorResource(id = R.color.white),
  390. // uncheckedTrackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
  391. uncheckedTrackColor = colorResource(id = R.color.switch_gray),
  392. // uncheckedBorderColor = MaterialTheme.colorScheme.surfaceContainerHighest
  393. uncheckedBorderColor = colorResource(id = R.color.switch_gray)
  394. ),
  395. thumbContent = {}
  396. )
  397. }
  398. }
  399. }
  400. @OptIn(ExperimentalMaterial3Api::class)
  401. @Composable
  402. fun ColumnScope.AddRowSettingsColumnTV(
  403. icon: Int,
  404. text: String,
  405. focusRequester1: FocusRequester,
  406. focusRequester2: FocusRequester
  407. ) {
  408. val context = LocalContext.current
  409. val basePreferenceHelper = BasePreferenceHelper(context = context)
  410. val availableProtocols = getAvailableProtocols(basePreferenceHelper)
  411. var isSheetOpen by remember { mutableStateOf(false) }
  412. val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
  413. val protocols = listOf(
  414. "Auto", "WireGuard", "IKEv2", "OpenVPN TCP", "OpenVPN UDP"
  415. )
  416. var selectedProtocol by remember { mutableStateOf(basePreferenceHelper.getProtocol().full_name) }
  417. var isFirstRowFocused by remember { mutableStateOf(false) }
  418. // val serverListViewModel = serverListViewModelSplash
  419. // val serverListViewModel: ServerListViewModel = viewModel{
  420. // ServerListViewModel(context)
  421. // }
  422. // val configuration = LocalConfiguration.current
  423. // val isTablet = configuration.screenWidthDp > 840
  424. Row(
  425. modifier = Modifier
  426. .fillMaxWidth()
  427. .padding(top = 5.dp, end = 27.dp)
  428. .clip(RoundedCornerShape(4.dp))
  429. .background(if (isFirstRowFocused) Color.LightGray else Color.White)
  430. .height(61.dp)
  431. .focusRequester(focusRequester1)
  432. .onFocusChanged {
  433. isFirstRowFocused = it.isFocused
  434. // if (!it.isFocused) focusRequester2.requestFocus()
  435. }
  436. .pointerInput(Unit) {
  437. detectTapGestures {
  438. isSheetOpen = true
  439. }
  440. }
  441. .clickable { isSheetOpen = true }
  442. ,
  443. horizontalArrangement = Arrangement.Start,
  444. verticalAlignment = Alignment.CenterVertically
  445. ) {
  446. Surface(
  447. modifier = Modifier.padding(start = 20.dp),
  448. color = Color.Transparent
  449. ) {
  450. Image(
  451. painter = painterResource(id = icon),
  452. contentDescription = "World",
  453. modifier = Modifier
  454. .padding(start = 0.dp)
  455. .size(24.dp)
  456. .weight(1f),
  457. colorFilter = ColorFilter.tint(
  458. MaterialTheme.colorScheme.inversePrimary)
  459. )
  460. }
  461. Surface(
  462. modifier = Modifier
  463. .padding(start = 0.dp)
  464. .align(Alignment.CenterVertically),
  465. color = Color.Transparent
  466. ) {
  467. Column(
  468. modifier = Modifier.background(Color.Transparent),
  469. verticalArrangement = Arrangement.Center
  470. ) {
  471. Text(text = text,
  472. color = MaterialTheme.colorScheme.inversePrimary,
  473. style = MaterialTheme.typography.titleSmall,
  474. maxLines = 1,
  475. modifier = Modifier
  476. .padding(start = 18.dp, end = 0.dp)
  477. // .weight(1f)
  478. )
  479. Spacer(modifier = Modifier.height(2.dp))
  480. Text(text = selectedProtocol,
  481. style = MaterialTheme.typography.headlineSmall.copy(
  482. fontSize = if (isTablet()) 14.sp else 12.sp
  483. ),
  484. color = MaterialTheme.colorScheme.inversePrimary,
  485. maxLines = 1,
  486. modifier = Modifier
  487. .padding(start = 18.dp, end = 0.dp)
  488. // .weight(1f)
  489. .alpha(0.6F),
  490. )
  491. }
  492. }
  493. Spacer(modifier = Modifier.weight(1f))
  494. Surface(
  495. modifier = Modifier
  496. .padding(end = 20.dp)
  497. .align(Alignment.CenterVertically),
  498. color = Color.Transparent
  499. ) {
  500. Image(
  501. painter = painterResource(id = R.drawable.frontarrow3x),
  502. contentDescription = "Front_Arrow",
  503. modifier = Modifier
  504. .padding(start = 0.dp, end = 0.dp)
  505. .size(10.dp, 18.dp)
  506. .weight(1f),
  507. colorFilter = ColorFilter.tint(
  508. MaterialTheme.colorScheme.inversePrimary
  509. )
  510. )
  511. }
  512. if (isSheetOpen) {
  513. ModalBottomSheet(
  514. onDismissRequest = { isSheetOpen = false },
  515. sheetState = sheetState,
  516. // containerColor = MaterialTheme.colorScheme.onBackground
  517. containerColor = Color.White,
  518. ) {
  519. Box(modifier = Modifier
  520. .background(Color.Transparent)
  521. .fillMaxWidth()
  522. .height(340.dp)
  523. .padding(start = 0.dp, top = 5.dp),
  524. ) {
  525. Column(
  526. verticalArrangement = Arrangement.Top,
  527. horizontalAlignment = Alignment.Start
  528. ) {
  529. AddTextSettings(
  530. text = "VPN Protocols",
  531. size = 18.sp,
  532. color = MaterialTheme.colorScheme.inversePrimary,
  533. bottomPadding = 15.dp,
  534. startPadding = 16.dp,
  535. style = MaterialTheme.typography.titleMedium
  536. )
  537. availableProtocols.forEach { protocol ->
  538. Row(
  539. modifier = Modifier
  540. .fillMaxWidth()
  541. .background(Color.Transparent)
  542. .padding(start = 2.dp)
  543. .selectable(
  544. selected = selectedProtocol == protocol,
  545. onClick = {
  546. selectedProtocol = protocol
  547. isSheetOpen = false
  548. // selectProtocolCallback(
  549. // protocol = protocol,
  550. // context,
  551. // serverListViewModel
  552. // )
  553. },
  554. )
  555. // .indication(
  556. // indication = null,
  557. // interactionSource = remember {
  558. // MutableInteractionSource()
  559. // }
  560. // )
  561. ,
  562. verticalAlignment = Alignment.CenterVertically
  563. ) {
  564. RadioButton(selected = protocol == selectedProtocol,
  565. onClick = {
  566. selectedProtocol = protocol
  567. isSheetOpen = false
  568. // selectProtocolCallback(protocol = protocol, context, serverListViewModel)
  569. },
  570. colors = RadioButtonDefaults.colors(
  571. selectedColor = colorResource(id = R.color.radio_button_blue),
  572. unselectedColor = colorResource(id = R.color.gray_icon),)
  573. )
  574. Text(text = protocol,
  575. modifier = Modifier.padding(start = 12.dp),
  576. color = MaterialTheme.colorScheme.inversePrimary,
  577. style = MaterialTheme.typography.bodySmall
  578. )
  579. }
  580. }
  581. }
  582. }
  583. }
  584. }
  585. }
  586. }
  587. @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
  588. @Composable
  589. fun ColumnScope.AddRowSettingsSmartTV(
  590. icon: Int,
  591. text: String,
  592. isRowShown: Boolean,
  593. isSheetShown: Boolean,
  594. navHostController: NavHostController,
  595. focusRequester2: FocusRequester,
  596. focusRequester3: FocusRequester
  597. ) {
  598. var isSmartSheetOpen by remember { mutableStateOf(false) }
  599. var isAnySpecificSheetOpen by remember { mutableStateOf(false) }
  600. val context = LocalContext.current
  601. val basePreferenceHelper = BasePreferenceHelper(context)
  602. var isRowFocused by remember { mutableStateOf(false) }
  603. // if (isRowShown) { }
  604. Row(
  605. modifier = Modifier
  606. .fillMaxWidth()
  607. .padding(top = 5.dp, end = 27.dp)
  608. .clip(RoundedCornerShape(4.dp))
  609. .background(if (isRowFocused) Color.LightGray else Color.White)
  610. // .focusRequester(focusRequester2)
  611. .onFocusChanged {
  612. isRowFocused = it.isFocused
  613. // if (!it.isFocused) focusRequester3.requestFocus()
  614. }
  615. .pointerInput(Unit) {
  616. detectTapGestures {
  617. isSmartSheetOpen = true
  618. }
  619. }
  620. .height(61.dp)
  621. .clickable { isSmartSheetOpen = true },
  622. horizontalArrangement = Arrangement.Start,
  623. verticalAlignment = Alignment.CenterVertically
  624. ) {
  625. Surface(
  626. modifier = Modifier.padding(start = 20.dp),
  627. color = Color.Transparent
  628. ) {
  629. Image(
  630. painter = painterResource(id = icon),
  631. contentDescription = "World",
  632. modifier = Modifier
  633. .padding(start = 0.dp)
  634. .size(24.dp)
  635. .weight(1f),
  636. colorFilter = ColorFilter.tint(
  637. MaterialTheme.colorScheme.inversePrimary)
  638. )
  639. }
  640. Surface(
  641. modifier = Modifier.padding(start = 0.dp),
  642. color = Color.Transparent
  643. ) {
  644. Text(text = text,
  645. style = MaterialTheme.typography.titleSmall,
  646. color = MaterialTheme.colorScheme.inversePrimary,
  647. maxLines = 1,
  648. modifier = Modifier
  649. .padding(start = 18.dp, end = 0.dp)
  650. .weight(1f)
  651. )
  652. }
  653. Spacer(modifier = Modifier.weight(1f))
  654. Surface(
  655. modifier = Modifier
  656. .padding(end = 20.dp)
  657. .align(Alignment.CenterVertically),
  658. color = Color.Transparent
  659. ) {
  660. Image(
  661. painter = painterResource(id = R.drawable.frontarrow3x),
  662. contentDescription = "Front_Arrow",
  663. modifier = Modifier
  664. .padding(start = 0.dp, end = 3.dp)
  665. .size(10.dp, 18.dp)
  666. .weight(1f),
  667. colorFilter = ColorFilter.tint(
  668. MaterialTheme.colorScheme.inversePrimary
  669. )
  670. )
  671. }
  672. }
  673. if (isSmartSheetOpen) {
  674. val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
  675. var selectedSmartConnect by remember {
  676. mutableStateOf(basePreferenceHelper.getSmartList()) }
  677. ModalBottomSheet(
  678. onDismissRequest = { isSmartSheetOpen = false
  679. BottomBarScreen.Settings.isTrue = false
  680. },
  681. sheetState = sheetState,
  682. containerColor = Color.White
  683. ) {
  684. Box(modifier = Modifier
  685. .background(Color.Transparent)
  686. .fillMaxWidth()
  687. .height(250.dp)
  688. .padding(start = 0.dp, top = 10.dp),
  689. ) {
  690. val selectedSmartList = basePreferenceHelper.getSmartList()
  691. val smartServer = basePreferenceHelper.getSmartServerObject() ?: basePreferenceHelper.getRecommendedServerObject()
  692. Column(
  693. verticalArrangement = Arrangement.Top,
  694. horizontalAlignment = Alignment.Start
  695. ) {
  696. AddTextSettings(
  697. text = "Smart Connect",
  698. size = 18.sp,
  699. color = MaterialTheme.colorScheme.inversePrimary,
  700. bottomPadding = 20.dp,
  701. startPadding = 16.dp,
  702. style = MaterialTheme.typography.titleMedium
  703. )
  704. smartConnect.forEach { smart ->
  705. Row(
  706. modifier = Modifier
  707. .fillMaxWidth()
  708. .background(Color.Transparent)
  709. .padding(start = 2.dp)
  710. .selectable(
  711. selected = selectedSmartConnect == smart,
  712. onClick = {
  713. selectedSmartConnect = smart
  714. basePreferenceHelper.saveSmartList(smart)
  715. isSmartSheetOpen = false
  716. if (smart == smartConnect[2]) {
  717. Log.d("smartLocationList Row", smart)
  718. isAnySpecificSheetOpen = true
  719. }
  720. },
  721. )
  722. // .indication(
  723. // indication = null,
  724. // interactionSource = remember {
  725. // MutableInteractionSource()
  726. // }
  727. // )
  728. ,
  729. verticalAlignment = Alignment.CenterVertically
  730. ) {
  731. RadioButton(selected = smart == selectedSmartConnect,
  732. onClick = {
  733. selectedSmartConnect = smart
  734. basePreferenceHelper.saveSmartList(smart)
  735. isSmartSheetOpen = false
  736. if (smart == smartConnect[2]) {
  737. Log.d("smartLocationList RB", smart)
  738. isAnySpecificSheetOpen = true
  739. }
  740. },
  741. colors = RadioButtonDefaults.colors(
  742. selectedColor = colorResource(id = R.color.radio_button_blue),
  743. unselectedColor = colorResource(id = R.color.gray_icon),)
  744. )
  745. Column {
  746. Text(text = smart,
  747. modifier = Modifier.padding(start = 12.dp),
  748. color = MaterialTheme.colorScheme.inversePrimary,
  749. style = MaterialTheme.typography.bodySmall
  750. )
  751. if (smart == smartConnect[2]) {
  752. if (selectedSmartList == smartConnect[2]) {
  753. Log.d("smartLocationList Row", smart)
  754. Text(text = "${smartServer?.server_name}",
  755. modifier = Modifier.padding(start = 12.dp),
  756. // color = MaterialTheme.colorScheme.inversePrimary,
  757. style = MaterialTheme.typography.labelLarge.copy(
  758. fontSize = 12.sp,
  759. color = colorResource(id = R.color.gray_icon)
  760. )
  761. )
  762. }
  763. }
  764. }
  765. }
  766. }
  767. }
  768. }
  769. }
  770. }
  771. if (isAnySpecificSheetOpen) {
  772. val sheetStateAny = rememberModalBottomSheetState(skipPartiallyExpanded = true)
  773. val searchListViewModel = searchListViewModelSplash
  774. // val searchText = searchListViewModel.searchText.observeAsState().value
  775. var searchText1 by remember { mutableStateOf("") }
  776. val isActive = searchListViewModel.isActive.observeAsState().value
  777. val scope = rememberCoroutineScope()
  778. ModalBottomSheet(
  779. onDismissRequest = { isAnySpecificSheetOpen = false
  780. BottomBarScreen.Settings.isTrue = false
  781. },
  782. sheetState = sheetStateAny,
  783. containerColor = Color.White,
  784. modifier = Modifier
  785. .padding(top = 15.dp)
  786. .fillMaxSize()
  787. ) {
  788. Box(modifier = Modifier
  789. .background(Color.Transparent)
  790. // .fillMaxWidth()
  791. // .fillMaxHeight()
  792. .padding(start = 0.dp, top = 10.dp)
  793. .fillMaxSize(),
  794. ) {
  795. Column(
  796. verticalArrangement = Arrangement.Top,
  797. horizontalAlignment = Alignment.Start
  798. ) {
  799. CompositionLocalProvider(
  800. LocalOverscrollConfiguration provides null
  801. ) {
  802. LaunchedEffect(key1 = searchText1) {
  803. Log.d("test_search_logic", "LaunchedEffect $searchText1")
  804. val delay = if (searchText1.isEmpty()) 0L else 300L
  805. delay(delay)
  806. val query = searchText1.ifEmpty { "settings_screen" }
  807. searchListViewModel.getCountries(query, true)
  808. }
  809. // if (isActive == false) {
  810. // searchText1 = ""
  811. // }
  812. DockedSearchBar(
  813. query = searchText1,
  814. onQueryChange = {
  815. searchText1 = it
  816. // scope.launch {
  817. // searchListViewModel.searchTextChange(it)
  818. // }
  819. },
  820. onSearch = {
  821. scope.launch {
  822. searchListViewModel.isActiveChange(state = false, true)
  823. }
  824. // keyboardController?.hide()
  825. },
  826. active = isActive!!,
  827. onActiveChange = {
  828. scope.launch {
  829. searchListViewModel.isActiveChange(it, isFromSettings = true)
  830. }
  831. },
  832. placeholder = {
  833. Text(
  834. text = "Search Location",
  835. style = MaterialTheme.typography.displaySmall,
  836. color = colorResource(id = R.color.dark_blue_gray_text)
  837. )
  838. },
  839. leadingIcon = {
  840. Icon(
  841. painter = painterResource(id = R.drawable.search3x),
  842. contentDescription = "Search Icon",
  843. modifier = Modifier
  844. .size(21.dp)
  845. )
  846. },
  847. colors = SearchBarDefaults.colors(
  848. containerColor = colorResource(id = R.color.white),
  849. dividerColor = Color.Transparent,
  850. inputFieldColors = TextFieldDefaults.colors(
  851. focusedTextColor = colorResource(id = R.color.dark_blue_gray_text),
  852. unfocusedTextColor = colorResource(id = R.color.dark_blue_gray_text),
  853. unfocusedIndicatorColor = colorResource(id = R.color.dark_blue_gray_text),
  854. focusedIndicatorColor = colorResource(id = R.color.dark_blue_gray_text),
  855. disabledIndicatorColor = colorResource(id = R.color.dark_blue_gray_text),
  856. cursorColor = colorResource(id = R.color.dark_blue_gray_text),
  857. )
  858. ),
  859. modifier = Modifier
  860. .fillMaxWidth()
  861. .height(50.dp)
  862. .padding(horizontal = 10.dp)
  863. .background(Color.Transparent)
  864. ) {}
  865. val searchServersList = searchListViewModel.countriesListSettings.observeAsState().value
  866. LazyColumn(
  867. modifier = Modifier
  868. .padding(top = 20.dp, bottom = 40.dp)
  869. ) {
  870. items(items = searchServersList!!) { server ->
  871. ServerSpecificItem(
  872. server, navHostController = navHostController,
  873. onServerDisable = { isAnySpecificSheetOpen = false }
  874. )
  875. }
  876. }
  877. }
  878. }
  879. }
  880. }
  881. }
  882. }
  883. @OptIn(ExperimentalMaterial3Api::class)
  884. @Composable
  885. fun AddRowDarkLightThemeTV(
  886. icon: ImageVector,
  887. text: String,
  888. ) {
  889. var isThemeSheetOpen by remember { mutableStateOf(false) }
  890. val sheetState = rememberModalBottomSheetState()
  891. val context = LocalContext.current
  892. val basePreferenceHelper = BasePreferenceHelper(context)
  893. val selectedtheme = remember { mutableStateOf(basePreferenceHelper.getTheme()) }
  894. val isSystemInDarkTheme = isSystemInDarkTheme()
  895. val systemTheme by remember { mutableStateOf(isSystemInDarkTheme) }
  896. Row(
  897. modifier = Modifier
  898. .fillMaxWidth()
  899. .padding(top = 40.dp, end = 27.dp)
  900. .background(Color.Transparent)
  901. .pointerInput(Unit) {
  902. detectTapGestures {
  903. isThemeSheetOpen = true
  904. }
  905. }
  906. .height(24.dp),
  907. horizontalArrangement = Arrangement.Start,
  908. verticalAlignment = Alignment.CenterVertically
  909. ) {
  910. Surface(
  911. modifier = Modifier.padding(start = 0.dp),
  912. color = Color.Transparent
  913. ) {
  914. Image(
  915. imageVector = icon,
  916. contentDescription = "Select Theme",
  917. modifier = Modifier
  918. .padding(start = 0.dp)
  919. .size(24.dp)
  920. .weight(1f),
  921. colorFilter = ColorFilter.tint(
  922. MaterialTheme.colorScheme.inversePrimary) )
  923. }
  924. Surface(
  925. modifier = Modifier.padding(start = 0.dp),
  926. color = Color.Transparent
  927. ) {
  928. Text(text = text,
  929. style = MaterialTheme.typography.titleMedium,
  930. color = MaterialTheme.colorScheme.inversePrimary,
  931. maxLines = 1,
  932. modifier = Modifier
  933. .padding(start = 18.dp, end = 0.dp)
  934. .weight(1f)
  935. )
  936. }
  937. Spacer(modifier = Modifier.weight(1f))
  938. Surface(
  939. modifier = Modifier
  940. .padding(start = 15.dp)
  941. .align(Alignment.CenterVertically),
  942. color = Color.Transparent
  943. ) {
  944. Image(
  945. painter = painterResource(id = R.drawable.frontarrow3x),
  946. contentDescription = "Front_Arrow",
  947. modifier = Modifier
  948. .padding(start = 0.dp, end = 0.dp)
  949. .size(10.dp, 18.dp)
  950. .weight(1f),
  951. colorFilter = ColorFilter.tint(
  952. MaterialTheme.colorScheme.inversePrimary
  953. )
  954. )
  955. }
  956. }
  957. if (isThemeSheetOpen) {
  958. ModalBottomSheet(
  959. onDismissRequest = { isThemeSheetOpen = false
  960. },
  961. sheetState = sheetState,
  962. containerColor = Color.White,
  963. ) {
  964. Box(modifier = Modifier
  965. .background(Color.Transparent)
  966. .fillMaxWidth()
  967. .height(250.dp)
  968. .padding(start = 0.dp, top = 10.dp),
  969. ) {
  970. Log.d("test_theme", "systemTheme -> $systemTheme")
  971. Column(
  972. verticalArrangement = Arrangement.Top,
  973. horizontalAlignment = Alignment.Start
  974. ) {
  975. AddTextSettings(
  976. text = "Theme",
  977. size = 18.sp,
  978. color = MaterialTheme.colorScheme.inversePrimary,
  979. bottomPadding = 20.dp,
  980. startPadding = 16.dp,
  981. style = MaterialTheme.typography.titleSmall
  982. )
  983. themesList.forEach { theme ->
  984. Row(
  985. modifier = Modifier
  986. .fillMaxWidth()
  987. .background(Color.Transparent)
  988. .padding(start = 2.dp)
  989. .selectable(
  990. selected = theme == selectedtheme.value,
  991. onClick = {
  992. selectedtheme.value = theme
  993. basePreferenceHelper.saveTheme(selectedtheme.value)
  994. if (selectedtheme.value == themesList[0]) {
  995. Log.d("test_theme", "true: -> $systemTheme")
  996. isDarkTheme.value = systemTheme
  997. } else {
  998. Log.d("test_theme", "false: -> $systemTheme")
  999. isDarkTheme.value = selectedtheme.value == themesList[2]
  1000. }
  1001. isThemeSheetOpen = false
  1002. },
  1003. )
  1004. // .indication(
  1005. // indication = null,
  1006. // interactionSource = remember {
  1007. // MutableInteractionSource()
  1008. // }
  1009. // )
  1010. ,
  1011. verticalAlignment = Alignment.CenterVertically
  1012. ) {
  1013. // val themeState = isSystemInDarkTheme()
  1014. // val isSystemInDarkTheme by remember { mutableStateOf(themeState) }
  1015. RadioButton(selected = theme == selectedtheme.value,
  1016. onClick = {
  1017. selectedtheme.value = theme
  1018. basePreferenceHelper.saveTheme(selectedtheme.value)
  1019. if (selectedtheme.value == themesList[0])
  1020. {
  1021. Log.d("test_theme", "true: -> $systemTheme")
  1022. isDarkTheme.value = systemTheme
  1023. }
  1024. else {
  1025. Log.d("test_theme", "false: -> $systemTheme")
  1026. isDarkTheme.value = selectedtheme.value == themesList[2]
  1027. }
  1028. isThemeSheetOpen = false
  1029. },
  1030. colors = RadioButtonDefaults.colors(
  1031. selectedColor = colorResource(id = R.color.radio_button_blue),
  1032. unselectedColor = colorResource(id = R.color.gray_icon),)
  1033. )
  1034. Text(text = theme,
  1035. modifier = Modifier.padding(start = 12.dp),
  1036. style = MaterialTheme.typography.bodySmall,
  1037. color = MaterialTheme.colorScheme.inversePrimary
  1038. )
  1039. }
  1040. }
  1041. }
  1042. }
  1043. }
  1044. }
  1045. }