diff --git a/src/main/java/org/pubvm/a3270/MainActivity.kt b/src/main/java/org/pubvm/a3270/MainActivity.kt index 0785736..d7347a5 100644 --- a/src/main/java/org/pubvm/a3270/MainActivity.kt +++ b/src/main/java/org/pubvm/a3270/MainActivity.kt @@ -218,6 +218,7 @@ fun MainScreen( autoHost.hostType, autoHost.useTls, autoHost.tlsVerifyCert, + autoHost.tn3270e, autoHost.graphicsMode ) } @@ -356,9 +357,9 @@ fun MainScreen( if (showConnectDialog) { ConnectDialog( onDismiss = { showConnectDialog = false }, - onConnect = { host, port, model, luName, hostType, useTls, tlsVerifyCert, graphicsMode -> + onConnect = { host, port, model, luName, hostType, useTls, tlsVerifyCert, tn3270e, graphicsMode -> showConnectDialog = false - viewModel.connect(host, port, model, luName, hostType, useTls, tlsVerifyCert, graphicsMode) + viewModel.connect(host, port, model, luName, hostType, useTls, tlsVerifyCert, tn3270e, graphicsMode) terminalInputViewRef?.showSoftKeyboard() } ) diff --git a/src/main/java/org/pubvm/a3270/TerminalViewModel.kt b/src/main/java/org/pubvm/a3270/TerminalViewModel.kt index 5f5e4ff..4f1afba 100644 --- a/src/main/java/org/pubvm/a3270/TerminalViewModel.kt +++ b/src/main/java/org/pubvm/a3270/TerminalViewModel.kt @@ -253,6 +253,7 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application hostType: String = "TSO", useTls: Boolean = false, tlsVerifyCert: Boolean = true, + tn3270e: Boolean = true, graphicsModeStr: String = "BOTH" ) { currentHost = host @@ -284,6 +285,7 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application val effectiveHost = parsedConfig.host val effectivePort = parsedConfig.port val effectiveTls = useTls || parsedConfig.isUseTls + val effectiveTn3270e = tn3270e && parsedConfig.isTn3270eEnabled val globalVerify = AppSettings.isVerifyCertsEnabled(getApplication()) val effectiveVerify = tlsVerifyCert && globalVerify val gMode = org.lib3270j.graphics.GraphicsMode.fromString(graphicsModeStr) @@ -298,6 +300,7 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application } isUseTls = effectiveTls isTlsVerifyCert = effectiveVerify + isTn3270eEnabled = effectiveTn3270e graphicsMode = gMode } diff --git a/src/main/java/org/pubvm/a3270/storage/HostStorage.kt b/src/main/java/org/pubvm/a3270/storage/HostStorage.kt index f37477a..7052b31 100644 --- a/src/main/java/org/pubvm/a3270/storage/HostStorage.kt +++ b/src/main/java/org/pubvm/a3270/storage/HostStorage.kt @@ -17,6 +17,7 @@ data class SavedHost( val hostType: String = "TSO", val useTls: Boolean = false, val tlsVerifyCert: Boolean = true, + val tn3270e: Boolean = true, val graphicsMode: String = "BOTH" ) { fun toJson(): JSONObject { @@ -31,6 +32,7 @@ data class SavedHost( put("hostType", hostType) put("useTls", useTls) put("tlsVerifyCert", tlsVerifyCert) + put("tn3270e", tn3270e) put("graphicsMode", graphicsMode) } } @@ -48,6 +50,7 @@ data class SavedHost( hostType = json.optString("hostType", "TSO"), useTls = json.optBoolean("useTls", false), tlsVerifyCert = json.optBoolean("tlsVerifyCert", true), + tn3270e = json.optBoolean("tn3270e", true), graphicsMode = json.optString("graphicsMode", "BOTH") ) } diff --git a/src/main/java/org/pubvm/a3270/ui/ConnectDialog.kt b/src/main/java/org/pubvm/a3270/ui/ConnectDialog.kt index 680ed1c..a2b2671 100644 --- a/src/main/java/org/pubvm/a3270/ui/ConnectDialog.kt +++ b/src/main/java/org/pubvm/a3270/ui/ConnectDialog.kt @@ -1,5 +1,6 @@ package org.pubvm.a3270.ui +import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -10,22 +11,34 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.window.DialogProperties import org.pubvm.a3270.storage.HostStorage import org.pubvm.a3270.storage.SavedHost @Composable fun ConnectDialog( onDismiss: () -> Unit, - onConnect: (host: String, port: Int, model: Int, luName: String, hostType: String, useTls: Boolean, tlsVerifyCert: Boolean, graphicsMode: String) -> Unit + onConnect: ( + host: String, + port: Int, + model: Int, + luName: String, + hostType: String, + useTls: Boolean, + tlsVerifyCert: Boolean, + tn3270e: Boolean, + graphicsMode: String + ) -> Unit ) { val context = LocalContext.current var savedHosts by remember { mutableStateOf(HostStorage.getSavedHosts(context)) } @@ -40,6 +53,7 @@ fun ConnectDialog( var hostType by remember { mutableStateOf("TSO") } var useTls by remember { mutableStateOf(false) } var tlsVerifyCert by remember { mutableStateOf(true) } + var tn3270e by remember { mutableStateOf(true) } var graphicsMode by remember { mutableStateOf("BOTH") } fun loadProfile(saved: SavedHost) { @@ -53,6 +67,7 @@ fun ConnectDialog( hostType = saved.hostType useTls = saved.useTls tlsVerifyCert = saved.tlsVerifyCert + tn3270e = saved.tn3270e graphicsMode = saved.graphicsMode } @@ -67,6 +82,7 @@ fun ConnectDialog( hostType = "TSO" useTls = false tlsVerifyCert = true + tn3270e = true graphicsMode = "BOTH" } @@ -85,6 +101,7 @@ fun ConnectDialog( hostType = hostType, useTls = useTls, tlsVerifyCert = tlsVerifyCert, + tn3270e = tn3270e, graphicsMode = graphicsMode ) HostStorage.saveHost(context, hostToSave) @@ -102,20 +119,24 @@ fun ConnectDialog( keyboardController?.show() } - Dialog(onDismissRequest = onDismiss) { + Dialog( + onDismissRequest = onDismiss, + properties = DialogProperties(usePlatformDefaultWidth = false) + ) { Surface( - shape = RoundedCornerShape(12.dp), + shape = RoundedCornerShape(16.dp), color = Color(0xFF1E1E1E), tonalElevation = 6.dp, modifier = Modifier - .fillMaxWidth(0.96f) - .wrapContentHeight() + .fillMaxWidth(0.95f) + .heightIn(max = 680.dp) + .padding(vertical = 16.dp) ) { Column( modifier = Modifier - .fillMaxWidth() - .padding(14.dp), - verticalArrangement = Arrangement.spacedBy(6.dp) + .fillMaxSize() + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) ) { // Title Row Row( @@ -123,12 +144,17 @@ fun ConnectDialog( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text("Connect / Manage Hosts", fontWeight = FontWeight.Bold, fontSize = 15.sp, color = Color.White) + Text( + "Connect / Manage Hosts", + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = Color.White + ) TextButton( onClick = { clearFields() }, - contentPadding = PaddingValues(horizontal = 6.dp, vertical = 2.dp) + contentPadding = PaddingValues(horizontal = 8.dp, vertical = 2.dp) ) { - Text("+ New Profile", fontSize = 12.sp) + Text("+ New Profile", fontSize = 12.sp, color = Color(0xFF339AF0)) } } @@ -136,18 +162,23 @@ fun ConnectDialog( Box( modifier = Modifier .fillMaxWidth() - .heightIn(max = 460.dp) + .weight(1f, fill = false) ) { val scrollState = rememberScrollState() Column( modifier = Modifier .fillMaxWidth() .verticalScroll(scrollState), - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(10.dp) ) { // Saved Profiles List Section if (savedHosts.isNotEmpty()) { - Text("Saved Host Profiles:", fontSize = 11.sp, fontWeight = FontWeight.Bold, color = Color.Gray) + Text( + "Saved Host Profiles:", + fontSize = 11.sp, + fontWeight = FontWeight.Bold, + color = Color.Gray + ) Column( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(4.dp) @@ -155,12 +186,13 @@ fun ConnectDialog( savedHosts.forEach { saved -> val isSelected = (saved.id == selectedHostId) val tlsTag = if (saved.useTls) { - if (saved.tlsVerifyCert) " [🔒 TLS]" else " [🔓 TLS/Unverified]" + if (saved.tlsVerifyCert) " [🔒 TLS]" else " [🔓 TLS/NoVerify]" } else "" + val eTag = if (!saved.tn3270e) " [Non-E]" else "" val gfxTag = if (saved.graphicsMode != "NONE") " [GFX: ${saved.graphicsMode}]" else "" Surface( - shape = RoundedCornerShape(6.dp), + shape = RoundedCornerShape(8.dp), color = if (isSelected) Color(0xFF2C3E50) else Color(0xFF25262B), border = if (isSelected) androidx.compose.foundation.BorderStroke(1.dp, Color(0xFF339AF0)) else null, modifier = Modifier @@ -170,7 +202,7 @@ fun ConnectDialog( Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 8.dp, vertical = 4.dp), + .padding(horizontal = 10.dp, vertical = 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { @@ -178,11 +210,11 @@ fun ConnectDialog( Text( text = saved.name, fontWeight = FontWeight.SemiBold, - fontSize = 12.sp, + fontSize = 13.sp, color = Color.White ) Text( - text = "${saved.host}:${saved.port} (M${saved.model} - ${saved.hostType})$tlsTag$gfxTag" + + text = "${saved.host}:${saved.port} (M${saved.model} - ${saved.hostType})$tlsTag$eTag$gfxTag" + if (saved.autoConnect) " [Auto]" else "", fontSize = 10.sp, color = Color.LightGray @@ -201,12 +233,13 @@ fun ConnectDialog( hostToConn.hostType, hostToConn.useTls, hostToConn.tlsVerifyCert, + hostToConn.tn3270e, hostToConn.graphicsMode ) }, - modifier = Modifier.size(28.dp) + modifier = Modifier.size(32.dp) ) { - Text("▶", fontSize = 13.sp, color = Color(0xFF51CF66)) + Text("▶", fontSize = 14.sp, color = Color(0xFF51CF66)) } IconButton( onClick = { @@ -216,20 +249,20 @@ fun ConnectDialog( clearFields() } }, - modifier = Modifier.size(28.dp) + modifier = Modifier.size(32.dp) ) { - Text("✕", fontSize = 12.sp, color = Color(0xFFFF6B6B)) + Text("✕", fontSize = 13.sp, color = Color(0xFFFF6B6B)) } } } } } } - HorizontalDivider(color = Color(0xFF373A40), modifier = Modifier.padding(vertical = 2.dp)) + HorizontalDivider(color = Color(0xFF373A40), modifier = Modifier.padding(vertical = 4.dp)) } Text( - text = if (selectedHostId != null) "Editing Profile:" else "New Profile Details:", + text = if (selectedHostId != null) "Editing Profile:" else "Host Connection Details:", fontSize = 11.sp, fontWeight = FontWeight.Bold, color = Color.Gray @@ -243,142 +276,236 @@ fun ConnectDialog( modifier = Modifier.fillMaxWidth() ) - OutlinedTextField( - value = host, - onValueChange = { host = it }, - label = { Text("Host / IP Address") }, - singleLine = true, - modifier = Modifier - .fillMaxWidth() - .focusRequester(focusRequester) - ) - - OutlinedTextField( - value = portStr, - onValueChange = { portStr = it }, - label = { Text("Port (default 23 or 992)") }, - singleLine = true, - modifier = Modifier.fillMaxWidth() - ) - - // Terminal Model Row( - horizontalArrangement = Arrangement.spacedBy(6.dp), - verticalAlignment = Alignment.CenterVertically + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - Text("Model:", fontSize = 11.sp, color = Color.Gray) - listOf(2, 3, 4, 5).forEach { m -> - FilterChip( - selected = (modelNum == m), - onClick = { modelNum = m }, - label = { Text("M$m", fontSize = 11.sp) } - ) + OutlinedTextField( + value = host, + onValueChange = { host = it }, + label = { Text("Host / IP Address") }, + singleLine = true, + modifier = Modifier + .weight(0.68f) + .focusRequester(focusRequester) + ) + OutlinedTextField( + value = portStr, + onValueChange = { portStr = it }, + label = { Text("Port") }, + singleLine = true, + modifier = Modifier.weight(0.32f) + ) + } + + // Terminal Model Selector + Column(modifier = Modifier.fillMaxWidth()) { + Text("Terminal Model:", fontSize = 11.sp, color = Color.Gray) + Spacer(modifier = Modifier.height(4.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + listOf( + 2 to "M2", + 3 to "M3", + 4 to "M4", + 5 to "M5" + ).forEach { (m, label) -> + val isSelected = (modelNum == m) + Surface( + shape = RoundedCornerShape(6.dp), + color = if (isSelected) Color(0xFF1C7ED6) else Color(0xFF2C2D30), + modifier = Modifier + .weight(1f) + .height(34.dp) + .clickable { modelNum = m } + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxSize().padding(horizontal = 2.dp) + ) { + Text( + text = label, + color = Color.White, + fontSize = 11.sp, + fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal, + textAlign = TextAlign.Center + ) + } + } + } } } // Host System Type (TSO, CMS, CICS) - Row( - horizontalArrangement = Arrangement.spacedBy(6.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text("Host Type:", fontSize = 11.sp, color = Color.Gray) - listOf("TSO", "CMS", "CICS").forEach { ht -> - FilterChip( - selected = (hostType == ht), - onClick = { hostType = ht }, - label = { Text(ht, fontSize = 11.sp) } - ) - } - } - - // Graphics Mode - Row( - horizontalArrangement = Arrangement.spacedBy(6.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text("Graphics:", fontSize = 11.sp, color = Color.Gray) - listOf( - "PROGRAMMED_SYMBOLS" to "Symbols", - "VECTOR_GRAPHICS" to "Vector", - "BOTH" to "Both", - "NONE" to "None" - ).forEach { (modeKey, modeLabel) -> - FilterChip( - selected = (graphicsMode.equals(modeKey, ignoreCase = true)), - onClick = { graphicsMode = modeKey }, - label = { Text(modeLabel, fontSize = 11.sp) } - ) - } - } - - // TLS / SSL Checkbox - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .clickable { - val newTls = !useTls - useTls = newTls - if (newTls && portStr.trim() == "23") { - portStr = "992" - } else if (!newTls && portStr.trim() == "992") { - portStr = "23" - } - } - ) { - Checkbox( - checked = useTls, - onCheckedChange = { checked -> - useTls = checked - if (checked && portStr.trim() == "23") { - portStr = "992" - } else if (!checked && portStr.trim() == "992") { - portStr = "23" - } - } - ) - Spacer(modifier = Modifier.width(4.dp)) - Text("Enable TLS / SSL Connection", fontSize = 12.sp, color = Color.White) - } - - // Verify Certificate Checkbox - if (useTls) { + Column(modifier = Modifier.fillMaxWidth()) { + Text("Host System Type:", fontSize = 11.sp, color = Color.Gray) + Spacer(modifier = Modifier.height(4.dp)) Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp) - .clickable { tlsVerifyCert = !tlsVerifyCert } + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(6.dp) ) { - Checkbox( - checked = tlsVerifyCert, - onCheckedChange = { tlsVerifyCert = it } - ) - Spacer(modifier = Modifier.width(4.dp)) - Text("Verify Server Certificate", fontSize = 12.sp, color = if (tlsVerifyCert) Color.LightGray else Color(0xFFFFB450)) + listOf("TSO", "CMS", "CICS").forEach { ht -> + val isSelected = (hostType == ht) + Surface( + shape = RoundedCornerShape(6.dp), + color = if (isSelected) Color(0xFF1C7ED6) else Color(0xFF2C2D30), + modifier = Modifier + .weight(1f) + .height(34.dp) + .clickable { hostType = ht } + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxSize() + ) { + Text( + text = ht, + color = Color.White, + fontSize = 11.sp, + fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal + ) + } + } + } + } + } + + // Graphics Mode (Both, Vector, Symbols, Off) + Column(modifier = Modifier.fillMaxWidth()) { + Text("Graphics Mode:", fontSize = 11.sp, color = Color.Gray) + Spacer(modifier = Modifier.height(4.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + listOf( + "BOTH" to "Both", + "VECTOR_GRAPHICS" to "Vector", + "PROGRAMMED_SYMBOLS" to "Symbols", + "NONE" to "Off" + ).forEach { (modeKey, modeLabel) -> + val isSelected = graphicsMode.equals(modeKey, ignoreCase = true) + Surface( + shape = RoundedCornerShape(6.dp), + color = if (isSelected) Color(0xFF2B8A3E) else Color(0xFF2C2D30), + modifier = Modifier + .weight(1f) + .height(34.dp) + .clickable { graphicsMode = modeKey } + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxSize().padding(horizontal = 2.dp) + ) { + Text( + text = modeLabel, + color = Color.White, + fontSize = 11.sp, + fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal, + textAlign = TextAlign.Center + ) + } + } + } } } OutlinedTextField( value = luName, onValueChange = { luName = it }, - label = { Text("LU Name (Optional)") }, + label = { Text("LU Name / Device Pool (Optional)") }, singleLine = true, modifier = Modifier.fillMaxWidth() ) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .clickable { autoConnect = !autoConnect } + // Protocol & Security Options + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(2.dp) ) { - Checkbox( - checked = autoConnect, - onCheckedChange = { autoConnect = it } - ) - Spacer(modifier = Modifier.width(4.dp)) - Text("Auto-connect on app startup", fontSize = 12.sp) + // TLS / SSL Checkbox + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable { + val newTls = !useTls + useTls = newTls + if (newTls && portStr.trim() == "23") { + portStr = "992" + } else if (!newTls && portStr.trim() == "992") { + portStr = "23" + } + } + ) { + Checkbox( + checked = useTls, + onCheckedChange = { checked -> + useTls = checked + if (checked && portStr.trim() == "23") { + portStr = "992" + } else if (!checked && portStr.trim() == "992") { + portStr = "23" + } + } + ) + Spacer(modifier = Modifier.width(4.dp)) + Text("Enable TLS / SSL Connection", fontSize = 12.sp, color = Color.White) + } + + // Verify Certificate Checkbox (only when TLS is active) + if (useTls) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(start = 24.dp) + .clickable { tlsVerifyCert = !tlsVerifyCert } + ) { + Checkbox( + checked = tlsVerifyCert, + onCheckedChange = { tlsVerifyCert = it } + ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + "Verify Server Certificate", + fontSize = 12.sp, + color = if (tlsVerifyCert) Color.LightGray else Color(0xFFFFB450) + ) + } + } + + // TN3270E Checkbox + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable { tn3270e = !tn3270e } + ) { + Checkbox( + checked = tn3270e, + onCheckedChange = { tn3270e = it } + ) + Spacer(modifier = Modifier.width(4.dp)) + Text("Enable TN3270E (Extended 3270)", fontSize = 12.sp, color = Color.White) + } + + // Auto-connect Checkbox + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable { autoConnect = !autoConnect } + ) { + Checkbox( + checked = autoConnect, + onCheckedChange = { autoConnect = it } + ) + Spacer(modifier = Modifier.width(4.dp)) + Text("Auto-connect on app startup", fontSize = 12.sp, color = Color.White) + } } } } @@ -392,13 +519,13 @@ fun ConnectDialog( verticalAlignment = Alignment.CenterVertically ) { TextButton(onClick = onDismiss) { - Text("Cancel") + Text("Cancel", color = Color.LightGray) } - Spacer(modifier = Modifier.width(4.dp)) + Spacer(modifier = Modifier.width(6.dp)) OutlinedButton(onClick = { saveCurrentProfile() }) { Text("Save") } - Spacer(modifier = Modifier.width(4.dp)) + Spacer(modifier = Modifier.width(6.dp)) Button( onClick = { val saved = saveCurrentProfile() @@ -411,12 +538,14 @@ fun ConnectDialog( saved.hostType, saved.useTls, saved.tlsVerifyCert, + saved.tn3270e, saved.graphicsMode ) } - } + }, + colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF2B8A3E)) ) { - Text("Connect") + Text("Connect", color = Color.White, fontWeight = FontWeight.Bold) } } } diff --git a/src/main/java/org/pubvm/a3270/ui/SettingsDialog.kt b/src/main/java/org/pubvm/a3270/ui/SettingsDialog.kt index 2a1e87b..66b4790 100644 --- a/src/main/java/org/pubvm/a3270/ui/SettingsDialog.kt +++ b/src/main/java/org/pubvm/a3270/ui/SettingsDialog.kt @@ -1,5 +1,6 @@ package org.pubvm.a3270.ui +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape @@ -14,6 +15,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties + @Composable fun SettingsDialog( initialMaskHiddenInput: Boolean, @@ -30,13 +33,17 @@ fun SettingsDialog( var verifyCerts by remember { mutableStateOf(initialVerifyCerts) } var defaultGraphicsMode by remember { mutableStateOf(initialDefaultGraphicsMode) } - Dialog(onDismissRequest = onDismiss) { + Dialog( + onDismissRequest = onDismiss, + properties = DialogProperties(usePlatformDefaultWidth = false) + ) { Card( - shape = RoundedCornerShape(12.dp), + shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color(0xFF1E1E1E)), modifier = Modifier - .fillMaxWidth() - .padding(16.dp) + .fillMaxWidth(0.95f) + .heightIn(max = 680.dp) + .padding(vertical = 16.dp) ) { Column( modifier = Modifier @@ -200,20 +207,37 @@ fun SettingsDialog( ) Spacer(modifier = Modifier.height(8.dp)) Row( - horizontalArrangement = Arrangement.spacedBy(6.dp), - verticalAlignment = Alignment.CenterVertically + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(6.dp) ) { listOf( "BOTH" to "Both", "VECTOR_GRAPHICS" to "Vector", "PROGRAMMED_SYMBOLS" to "Symbols", - "NONE" to "None" + "NONE" to "Off" ).forEach { (modeKey, modeLabel) -> - FilterChip( - selected = defaultGraphicsMode.equals(modeKey, ignoreCase = true), - onClick = { defaultGraphicsMode = modeKey }, - label = { Text(modeLabel, fontSize = 11.sp) } - ) + val isSelected = defaultGraphicsMode.equals(modeKey, ignoreCase = true) + Surface( + shape = RoundedCornerShape(6.dp), + color = if (isSelected) Color(0xFF2B8A3E) else Color(0xFF2C2D30), + modifier = Modifier + .weight(1f) + .height(34.dp) + .clickable { defaultGraphicsMode = modeKey } + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxSize().padding(horizontal = 2.dp) + ) { + Text( + text = modeLabel, + color = Color.White, + fontSize = 11.sp, + fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal, + textAlign = androidx.compose.ui.text.style.TextAlign.Center + ) + } + } } } }