package com.syncflow.ui.settings import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.syncflow.data.db.entities.CloudAccountEntity import com.syncflow.domain.model.ProviderType @Composable fun SettingsScreen( onAddAccount: () -> Unit, modifier: Modifier = Modifier, vm: SettingsViewModel = hiltViewModel(), ) { val accounts by vm.accounts.collectAsState() val biometricEnabled by vm.biometricEnabled.collectAsState() var deleteTarget by remember { mutableStateOf(null) } deleteTarget?.let { acct -> AlertDialog( onDismissRequest = { deleteTarget = null }, title = { Text("Remove account?") }, text = { Text("\"${acct.displayName}\" and all associated sync pairs will be removed.") }, confirmButton = { TextButton( onClick = { vm.removeAccount(acct); deleteTarget = null }, colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error), ) { Text("Remove") } }, dismissButton = { TextButton(onClick = { deleteTarget = null }) { Text("Cancel") } }, ) } LazyColumn( modifier = modifier.fillMaxSize(), contentPadding = PaddingValues(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp), ) { item { SectionHeader(title = "Cloud Accounts") Spacer(Modifier.height(4.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End, ) { FilledTonalButton(onClick = onAddAccount) { Icon(Icons.Default.Add, null, Modifier.size(18.dp)) Spacer(Modifier.width(6.dp)) Text("Add Account") } } } if (accounts.isEmpty()) { item { Column( modifier = Modifier.fillMaxWidth().padding(vertical = 24.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(8.dp), ) { Icon( Icons.Default.CloudOff, null, Modifier.size(48.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f), ) Text( "No accounts yet", style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) Text( "Add a cloud account to start syncing", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) OutlinedButton(onClick = onAddAccount) { Icon(Icons.Default.Add, null, Modifier.size(16.dp)) Spacer(Modifier.width(6.dp)) Text("Add your first account") } } } } else { items(accounts, key = { it.id }) { acct -> AccountCard(acct = acct, onDelete = { deleteTarget = acct }) } } item { Spacer(Modifier.height(8.dp)) SectionHeader(title = "Security") Spacer(Modifier.height(4.dp)) Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface), ) { Row( modifier = Modifier.fillMaxWidth().padding(16.dp), verticalAlignment = Alignment.CenterVertically, ) { Column(modifier = Modifier.weight(1f)) { Text("Biometric Lock", style = MaterialTheme.typography.bodyMedium) Text( "Require biometrics when returning to app", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) } Switch(checked = biometricEnabled, onCheckedChange = { vm.setBiometricLock(it) }) } } } item { Spacer(Modifier.height(8.dp)) SectionHeader(title = "About") Spacer(Modifier.height(4.dp)) Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface), ) { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(4.dp)) { Text( "SyncFlow", style = MaterialTheme.typography.titleSmall, ) Text( "Version ${com.syncflow.BuildConfig.VERSION_NAME} (build ${com.syncflow.BuildConfig.VERSION_CODE})", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) Spacer(Modifier.height(2.dp)) Text( "Free, no subscription. No ads. No tracking.", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } } } } @Composable private fun SectionHeader(title: String) { Row(verticalAlignment = Alignment.CenterVertically) { Box( modifier = Modifier .width(3.dp) .height(16.dp) .clip(RoundedCornerShape(2.dp)), ) { Surface(color = MaterialTheme.colorScheme.primary, modifier = Modifier.fillMaxSize()) {} } Spacer(Modifier.width(8.dp)) Text( title, style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onBackground, ) } } @Composable private fun AccountCard(acct: CloudAccountEntity, onDelete: () -> Unit) { Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface), ) { Row(modifier = Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically) { // Icon with primaryContainer background Surface( shape = RoundedCornerShape(12.dp), color = MaterialTheme.colorScheme.primaryContainer, modifier = Modifier.size(40.dp), ) { Box(contentAlignment = Alignment.Center) { Icon( providerIcon(acct.providerType), null, Modifier.size(22.dp), tint = MaterialTheme.colorScheme.onPrimaryContainer, ) } } Spacer(Modifier.width(12.dp)) Column(modifier = Modifier.weight(1f)) { Text(acct.displayName, style = MaterialTheme.typography.bodyMedium) Text( buildString { append(friendlyProviderName(acct.providerType)) acct.email?.let { append(" ยท $it") } }, style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) acct.serverUrl?.let { Text(it, style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant) } } IconButton(onClick = onDelete) { Icon(Icons.Default.Delete, "Remove", tint = MaterialTheme.colorScheme.error) } } } } private fun providerIcon(type: ProviderType) = when (type) { ProviderType.GOOGLE_DRIVE -> Icons.Default.Cloud ProviderType.DROPBOX -> Icons.Default.CloudQueue ProviderType.ONEDRIVE -> Icons.Default.CloudDone ProviderType.WEBDAV -> Icons.Default.Storage ProviderType.SFTP -> Icons.Default.Terminal ProviderType.NEXTCLOUD -> Icons.Default.CloudCircle ProviderType.OWNCLOUD -> Icons.Default.CloudCircle ProviderType.SFTPGO -> Icons.Default.Storage } private fun friendlyProviderName(type: ProviderType) = when (type) { ProviderType.GOOGLE_DRIVE -> "Google Drive" ProviderType.DROPBOX -> "Dropbox" ProviderType.ONEDRIVE -> "OneDrive" ProviderType.WEBDAV -> "WebDAV" ProviderType.SFTP -> "SFTP" ProviderType.NEXTCLOUD -> "Nextcloud" ProviderType.OWNCLOUD -> "ownCloud" ProviderType.SFTPGO -> "SFTPGo" }