Version bump
Build and Test a3270 / Build Android APK (push) Successful in 5m36s
Release a3270 / Build & Publish Release (push) Successful in 5m40s

This commit is contained in:
2026-10-28 18:09:40 +00:00
parent 207fa48f15
commit ecae8c0669
4 changed files with 100 additions and 66 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ android {
minSdk 24 minSdk 24
targetSdk 34 targetSdk 34
versionCode 10 versionCode 10
versionName "1.3.0" versionName "1.2.5"
} }
buildTypes { buildTypes {
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="10" android:versionCode="10"
android:versionName="1.3.0"> android:versionName="1.2.5">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -508,9 +508,14 @@ fun FileTransferDialog(
} }
} }
// TSO Send Options // TSO / CMS Allocation & Record Format Options
if (!isReceive && hostType == FTConfig.HostType.TSO) { if (!isReceive && (hostType == FTConfig.HostType.TSO || hostType == FTConfig.HostType.CMS)) {
Text("TSO Dataset Allocation:", fontSize = 12.sp, fontWeight = FontWeight.Bold, color = Color.Gray) Text(
if (hostType == FTConfig.HostType.TSO) "TSO Dataset Allocation:" else "VM/CMS File Format:",
fontSize = 12.sp,
fontWeight = FontWeight.Bold,
color = Color.Gray
)
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
@@ -542,64 +547,70 @@ fun FileTransferDialog(
onValueChange = { lreclStr = it.filter { c -> c.isDigit() } }, onValueChange = { lreclStr = it.filter { c -> c.isDigit() } },
label = { Text("LRECL", fontSize = 11.sp) }, label = { Text("LRECL", fontSize = 11.sp) },
singleLine = true, singleLine = true,
keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next), keyboardOptions = TerminalKeyboardOptions.copy(
modifier = Modifier.weight(1f) imeAction = if (hostType == FTConfig.HostType.TSO) ImeAction.Next else ImeAction.Done
),
modifier = if (hostType == FTConfig.HostType.TSO) Modifier.weight(1f) else Modifier.fillMaxWidth()
) )
OutlinedTextField( if (hostType == FTConfig.HostType.TSO) {
value = blksizeStr, OutlinedTextField(
onValueChange = { blksizeStr = it.filter { c -> c.isDigit() } }, value = blksizeStr,
label = { Text("BLKSIZE", fontSize = 11.sp) }, onValueChange = { blksizeStr = it.filter { c -> c.isDigit() } },
singleLine = true, label = { Text("BLKSIZE", fontSize = 11.sp) },
keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next), singleLine = true,
modifier = Modifier.weight(1f) keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next),
) modifier = Modifier.weight(1f)
} )
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text("Units:", fontSize = 11.sp)
Row {
listOf(
FTConfig.AllocationUnit.TRACKS to "Tracks",
FTConfig.AllocationUnit.CYLINDERS to "Cylinders",
FTConfig.AllocationUnit.AVBLOCK to "Avblock",
FTConfig.AllocationUnit.DEFAULT to "Default"
).forEach { (u, label) ->
FilterChip(
selected = (units == u),
onClick = { units = u },
label = { Text(label, fontSize = 11.sp) }
)
Spacer(modifier = Modifier.width(4.dp))
}
} }
} }
Row( if (hostType == FTConfig.HostType.TSO) {
modifier = Modifier.fillMaxWidth(), Row(
horizontalArrangement = Arrangement.spacedBy(8.dp) modifier = Modifier.fillMaxWidth(),
) { horizontalArrangement = Arrangement.SpaceBetween,
OutlinedTextField( verticalAlignment = Alignment.CenterVertically
value = spaceStr, ) {
onValueChange = { spaceStr = it }, Text("Units:", fontSize = 11.sp)
label = { Text("SPACE (Pri, Sec)", fontSize = 11.sp) }, Row {
placeholder = { Text("e.g. 5,2 or 1,1") }, listOf(
singleLine = true, FTConfig.AllocationUnit.TRACKS to "Tracks",
keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next), FTConfig.AllocationUnit.CYLINDERS to "Cylinders",
modifier = Modifier.weight(0.62f) FTConfig.AllocationUnit.AVBLOCK to "Avblock",
) FTConfig.AllocationUnit.DEFAULT to "Default"
OutlinedTextField( ).forEach { (u, label) ->
value = dirBlocks, FilterChip(
onValueChange = { dirBlocks = it.filter { c -> c.isDigit() } }, selected = (units == u),
label = { Text("Dir (PDS)", fontSize = 11.sp) }, onClick = { units = u },
placeholder = { Text("e.g. 10") }, label = { Text(label, fontSize = 11.sp) }
singleLine = true, )
keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Done), Spacer(modifier = Modifier.width(4.dp))
modifier = Modifier.weight(0.38f) }
) }
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = spaceStr,
onValueChange = { spaceStr = it },
label = { Text("SPACE (Pri, Sec)", fontSize = 11.sp) },
placeholder = { Text("e.g. 5,2 or 1,1") },
singleLine = true,
keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next),
modifier = Modifier.weight(0.62f)
)
OutlinedTextField(
value = dirBlocks,
onValueChange = { dirBlocks = it.filter { c -> c.isDigit() } },
label = { Text("Dir (PDS)", fontSize = 11.sp) },
placeholder = { Text("e.g. 10") },
singleLine = true,
keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Done),
modifier = Modifier.weight(0.38f)
)
}
} }
} }
@@ -637,13 +648,17 @@ fun FileTransferDialog(
setTransferMode(if (isAscii) FTConfig.TransferMode.ASCII else FTConfig.TransferMode.BINARY) setTransferMode(if (isAscii) FTConfig.TransferMode.ASCII else FTConfig.TransferMode.BINARY)
setHostType(hostType) setHostType(hostType)
setExistAction(if (overwrite) FTConfig.ExistAction.REPLACE else FTConfig.ExistAction.KEEP) setExistAction(if (overwrite) FTConfig.ExistAction.REPLACE else FTConfig.ExistAction.KEEP)
if (!isReceive && hostType == FTConfig.HostType.TSO) { if (!isReceive) {
setRecfm(recfm) if (hostType == FTConfig.HostType.TSO || hostType == FTConfig.HostType.CMS) {
lreclStr.trim().toIntOrNull()?.let { setLrecl(it) } setRecfm(recfm)
blksizeStr.trim().toIntOrNull()?.let { setBlksize(it) } lreclStr.trim().toIntOrNull()?.let { setLrecl(it) }
setUnits(units) }
if (spaceStr.isNotBlank()) setSpace(spaceStr.trim()) if (hostType == FTConfig.HostType.TSO) {
if (dirBlocks.isNotBlank()) setDirectoryBlocks(dirBlocks.trim()) blksizeStr.trim().toIntOrNull()?.let { setBlksize(it) }
setUnits(units)
if (spaceStr.isNotBlank()) setSpace(spaceStr.trim())
if (dirBlocks.isNotBlank()) setDirectoryBlocks(dirBlocks.trim())
}
} }
if (hostType == FTConfig.HostType.CMS && cmsOptions.isNotBlank()) { if (hostType == FTConfig.HostType.CMS && cmsOptions.isNotBlank()) {
setOptions(cmsOptions.trim()) setOptions(cmsOptions.trim())
@@ -229,6 +229,25 @@ class ConnectionAndHostDirectoryTest {
assertEquals(FTConfig.HostType.CMS, state.hostType) assertEquals(FTConfig.HostType.CMS, state.hostType)
} }
@Test
fun testCmsFileTransferCommandGeneration() {
val cfg = FTConfig().apply {
setHostFilename("PROFILE EXEC A")
setLocalFilename("/tmp/profile.exec")
setDirection(FTConfig.Direction.SEND)
setTransferMode(FTConfig.TransferMode.ASCII)
setHostType(FTConfig.HostType.CMS)
setExistAction(FTConfig.ExistAction.REPLACE)
setRecfm(FTConfig.RecordFormat.FIXED)
setLrecl(80)
}
val cmd = cfg.buildCommand()
assertTrue("CMS command must contain RECFM F", cmd.contains("RECFM F"))
assertTrue("CMS command must contain LRECL 80", cmd.contains("LRECL 80"))
assertFalse("CMS command must not contain REPLACE keyword", cmd.contains("REPLACE"))
assertFalse("CMS command must not contain BLOCK keyword", cmd.contains("BLOCK"))
}
@Test @Test
fun testConnectChoiceEnum() { fun testConnectChoiceEnum() {
val choices = ConnectChoice.values() val choices = ConnectChoice.values()