v1.2.2: fix hidden TextField value sync & keyboard trigger

- Use mutableStateOf(TextFieldValue) as single source of truth
- Removed key(currentInput) that caused focus loss on each keystroke
- Changed hidden field from 0x0 to 1x30dp for better IME compatibility
- Fixed display: showing inputText.text instead of stale currentInput
- Soft keyboard now shows input text in terminal's last line
This commit is contained in:
茂之钳
2026-05-24 10:35:17 +00:00
parent 513121d884
commit b3281928f1
@@ -417,7 +417,8 @@ fun SshTerminalScreen(
modifier: Modifier = Modifier
) {
val state by manager.connectionState.collectAsState()
var currentInput by remember { mutableStateOf("") }
val inputState = remember { mutableStateOf(TextFieldValue("")) }
var currentInput by inputState
val coroutineScope = rememberCoroutineScope()
val listState = rememberLazyListState()
var showFontPicker by remember { mutableStateOf(false) }
@@ -435,24 +436,29 @@ fun SshTerminalScreen(
}
}
// 键盘事件处理
// 获取当前输入的纯文本(用于显示)
val currentInputText = currentInput.text
// 硬件键盘处理
fun handleKeyEvent(event: KeyEvent): Boolean {
if (!state.connected) return false
return when (event.type) {
KeyEventType.KeyUp -> {
when (event.key) {
Key.Enter -> {
if (currentInput.isNotEmpty()) {
val cmd = currentInputText.trim()
if (cmd.isNotEmpty()) {
coroutineScope.launch {
manager.sendCommand(currentInput)
currentInput = ""
manager.sendCommand(cmd)
}
}
currentInput = TextFieldValue("")
true
}
Key.Backspace -> {
if (currentInput.isNotEmpty()) {
currentInput = currentInput.substring(0, currentInput.length - 1)
val t = currentInputText
if (t.isNotEmpty()) {
currentInput = TextFieldValue(t.substring(0, t.length - 1))
}
true
}
@@ -472,36 +478,34 @@ fun SshTerminalScreen(
}
}
// 透明输入桥 — 用于弹出软键盘
Box(
modifier = modifier
.fillMaxSize()
.background(bg)
.onKeyEvent { handleKeyEvent(it) }
.focusRequester(focusModifier)
.clickable { focusModifier.requestFocus() }
) {
// 透明输入框 — 0 高度 + Invisible,仅用来弹出软键盘
// 透明输入框 — 极小的 1x30 dp,仅用来弹出软键盘
BasicTextField(
value = TextFieldValue(currentInput),
value = currentInput,
onValueChange = { newVal ->
val old = currentInput
currentInput = newVal.text
// 检测回车:如果内容有换行符说明用户按了发送
if (newVal.text.contains('\n')) {
val cmd = newVal.text.replace("\n", "").trim()
val t = newVal.text
if (t.endsWith('\n')) {
val cmd = t.dropLast(1).trim()
if (cmd.isNotEmpty()) {
coroutineScope.launch {
manager.sendCommand(cmd)
}
}
currentInput = ""
currentInput = TextFieldValue("")
} else {
currentInput = newVal
}
},
modifier = Modifier
.size(0.dp, 0.dp) // 零尺寸,不占据空间
.width(1.dp)
.height(30.dp)
.focusRequester(focusModifier),
singleLine = true,
textStyle = TextStyle(color = Color.Transparent, fontSize = 1.sp)
@@ -624,7 +628,7 @@ fun SshTerminalScreen(
}
item(key = "prompt") {
Text(
text = "\$ $currentInput",
text = "\$ $currentInputText",
color = textPrimary,
fontSize = terminalFontSizeSp,
fontFamily = FontFamily.Monospace,