package com.parseable.android.ui.screens.settings import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.parseable.android.BuildConfig import kotlinx.serialization.json.contentOrNull import kotlinx.serialization.json.jsonPrimitive @OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingsScreen( onBack: () -> Unit, viewModel: SettingsViewModel = hiltViewModel(), ) { val state by viewModel.state.collectAsStateWithLifecycle() Scaffold( topBar = { TopAppBar( title = { Text("Settings") }, navigationIcon = { IconButton(onClick = onBack) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back") } }, ) }, ) { padding -> PullToRefreshBox( isRefreshing = state.isLoading, onRefresh = viewModel::load, modifier = Modifier .fillMaxSize() .padding(padding), ) { Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp), ) { // Server info Card( modifier = Modifier.fillMaxWidth(), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), ) { Column(modifier = Modifier.padding(16.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( Icons.Filled.Dns, contentDescription = "Server connection", tint = MaterialTheme.colorScheme.primary, ) Spacer(modifier = Modifier.width(8.dp)) Text( text = "Server Connection", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, ) } Spacer(modifier = Modifier.height(12.dp)) SettingsRow("URL", state.serverUrl) SettingsRow("Username", state.username) SettingsRow("TLS", if (state.useTls) "Enabled" else "Disabled") } } // Loading indicator for server data if (state.isLoading) { Box( modifier = Modifier .fillMaxWidth() .padding(vertical = 8.dp), contentAlignment = Alignment.Center, ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp), ) { CircularProgressIndicator( modifier = Modifier.size(16.dp), strokeWidth = 2.dp, ) Text( text = "Loading server info...", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } } // Error from loading server data state.error?.let { errorText -> Card( colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.errorContainer, ), modifier = Modifier.fillMaxWidth(), ) { Row( modifier = Modifier.padding(16.dp), verticalAlignment = Alignment.CenterVertically, ) { Icon( Icons.Filled.ErrorOutline, contentDescription = "Error", tint = MaterialTheme.colorScheme.onErrorContainer, ) Spacer(modifier = Modifier.width(8.dp)) Text( text = errorText, color = MaterialTheme.colorScheme.onErrorContainer, style = MaterialTheme.typography.bodyMedium, ) } } } // About info state.aboutInfo?.let { about -> Card( modifier = Modifier.fillMaxWidth(), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), ) { Column(modifier = Modifier.padding(16.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( Icons.Filled.Info, contentDescription = "Server info", tint = MaterialTheme.colorScheme.primary, ) Spacer(modifier = Modifier.width(8.dp)) Text( text = "Server Info", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, ) } Spacer(modifier = Modifier.height(12.dp)) about.version?.let { SettingsRow("Version", it) } about.commit?.let { SettingsRow("Commit", it.take(12)) } about.mode?.let { SettingsRow("Mode", it) } about.license?.get("name")?.jsonPrimitive?.contentOrNull?.let { SettingsRow("License", it) } about.deploymentId?.let { SettingsRow("Deployment ID", it.take(12)) } about.queryEngine?.let { SettingsRow("Query Engine", it) } } } } // Users section if (state.users.isNotEmpty()) { Card( modifier = Modifier.fillMaxWidth(), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), ) { Column(modifier = Modifier.padding(16.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( Icons.Filled.People, contentDescription = "Users", tint = MaterialTheme.colorScheme.primary, ) Spacer(modifier = Modifier.width(8.dp)) Text( text = "Users (${state.users.size})", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, ) } Spacer(modifier = Modifier.height(12.dp)) state.users.forEach { user -> Text( text = user, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.padding(vertical = 4.dp), ) } } } } // App info Card( modifier = Modifier.fillMaxWidth(), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), ) { Column(modifier = Modifier.padding(16.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( Icons.Filled.PhoneAndroid, contentDescription = "App info", tint = MaterialTheme.colorScheme.primary, ) Spacer(modifier = Modifier.width(8.dp)) Text( text = "App", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, ) } Spacer(modifier = Modifier.height(12.dp)) SettingsRow("App Version", BuildConfig.VERSION_NAME) SettingsRow("Platform", "Android") } } } } } } @Composable private fun SettingsRow(label: String, value: String) { Row( modifier = Modifier .fillMaxWidth() .padding(vertical = 4.dp), horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = label, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) Text( text = value, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Medium, ) } }