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:
@@ -417,7 +417,8 @@ fun SshTerminalScreen(
|
|||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val state by manager.connectionState.collectAsState()
|
val state by manager.connectionState.collectAsState()
|
||||||
var currentInput by remember { mutableStateOf("") }
|
val inputState = remember { mutableStateOf(TextFieldValue("")) }
|
||||||
|
var currentInput by inputState
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
var showFontPicker by remember { mutableStateOf(false) }
|
var showFontPicker by remember { mutableStateOf(false) }
|
||||||
@@ -435,24 +436,29 @@ fun SshTerminalScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 键盘事件处理
|
// 获取当前输入的纯文本(用于显示)
|
||||||
|
val currentInputText = currentInput.text
|
||||||
|
|
||||||
|
// 硬件键盘处理
|
||||||
fun handleKeyEvent(event: KeyEvent): Boolean {
|
fun handleKeyEvent(event: KeyEvent): Boolean {
|
||||||
if (!state.connected) return false
|
if (!state.connected) return false
|
||||||
return when (event.type) {
|
return when (event.type) {
|
||||||
KeyEventType.KeyUp -> {
|
KeyEventType.KeyUp -> {
|
||||||
when (event.key) {
|
when (event.key) {
|
||||||
Key.Enter -> {
|
Key.Enter -> {
|
||||||
if (currentInput.isNotEmpty()) {
|
val cmd = currentInputText.trim()
|
||||||
|
if (cmd.isNotEmpty()) {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
manager.sendCommand(currentInput)
|
manager.sendCommand(cmd)
|
||||||
currentInput = ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
currentInput = TextFieldValue("")
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Key.Backspace -> {
|
Key.Backspace -> {
|
||||||
if (currentInput.isNotEmpty()) {
|
val t = currentInputText
|
||||||
currentInput = currentInput.substring(0, currentInput.length - 1)
|
if (t.isNotEmpty()) {
|
||||||
|
currentInput = TextFieldValue(t.substring(0, t.length - 1))
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -472,36 +478,34 @@ fun SshTerminalScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 透明输入桥 — 用于弹出软键盘
|
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(bg)
|
.background(bg)
|
||||||
.onKeyEvent { handleKeyEvent(it) }
|
.onKeyEvent { handleKeyEvent(it) }
|
||||||
.focusRequester(focusModifier)
|
.focusRequester(focusModifier)
|
||||||
|
|
||||||
.clickable { focusModifier.requestFocus() }
|
.clickable { focusModifier.requestFocus() }
|
||||||
) {
|
) {
|
||||||
// 透明输入框 — 0 高度 + Invisible,仅用来弹出软键盘
|
// 透明输入框 — 极小的 1x30 dp,仅用来弹出软键盘
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
value = TextFieldValue(currentInput),
|
value = currentInput,
|
||||||
onValueChange = { newVal ->
|
onValueChange = { newVal ->
|
||||||
val old = currentInput
|
val t = newVal.text
|
||||||
currentInput = newVal.text
|
if (t.endsWith('\n')) {
|
||||||
// 检测回车:如果内容有换行符说明用户按了发送
|
val cmd = t.dropLast(1).trim()
|
||||||
if (newVal.text.contains('\n')) {
|
|
||||||
val cmd = newVal.text.replace("\n", "").trim()
|
|
||||||
if (cmd.isNotEmpty()) {
|
if (cmd.isNotEmpty()) {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
manager.sendCommand(cmd)
|
manager.sendCommand(cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentInput = ""
|
currentInput = TextFieldValue("")
|
||||||
|
} else {
|
||||||
|
currentInput = newVal
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(0.dp, 0.dp) // 零尺寸,不占据空间
|
.width(1.dp)
|
||||||
|
.height(30.dp)
|
||||||
.focusRequester(focusModifier),
|
.focusRequester(focusModifier),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
textStyle = TextStyle(color = Color.Transparent, fontSize = 1.sp)
|
textStyle = TextStyle(color = Color.Transparent, fontSize = 1.sp)
|
||||||
@@ -624,7 +628,7 @@ fun SshTerminalScreen(
|
|||||||
}
|
}
|
||||||
item(key = "prompt") {
|
item(key = "prompt") {
|
||||||
Text(
|
Text(
|
||||||
text = "\$ $currentInput",
|
text = "\$ $currentInputText",
|
||||||
color = textPrimary,
|
color = textPrimary,
|
||||||
fontSize = terminalFontSizeSp,
|
fontSize = terminalFontSizeSp,
|
||||||
fontFamily = FontFamily.Monospace,
|
fontFamily = FontFamily.Monospace,
|
||||||
|
|||||||
Reference in New Issue
Block a user