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