authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-07-16 16:17:03+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-07-16 16:17:03+02:00
log5d68fca8f210c137eee04da30ed25b5fa7e432d9
tree532ac40efe5719e2d35e300543787d978d7a3ef3
parent2a33a18716854b8d07378008cf3101ad999209ae
signature Signed by PGP key B5690EEEBB952194

Fix iOS terminal Enter input encoding (#4043)


3 files changed, 22 insertions(+), 4 deletions(-)

apps/mobile/modules/t3-terminal/ios/T3TerminalModule.swift+1-1
......@@ -7,7 +7,7 @@ public class T3TerminalModule: Module {
77 // Bumped when native hardware-keyboard handling changes; surfaced in the JS debug
88 // logs so a stale native binary is distinguishable from a broken key pipeline.
99 Constants([
10 "hardwareKeyRevision": 2,
10 "hardwareKeyRevision": 3,
1111 ])
1212
1313 View(T3TerminalView.self) {
apps/mobile/modules/t3-terminal/ios/T3TerminalView.swift+19-2
......@@ -119,6 +119,21 @@ private enum TerminalHardwareKeyEncoder {
119119 }
120120}
121121
122private enum TerminalInputSequence {
123 /// Terminal Enter is carriage return. Sending line feed instead is Ctrl+J,
124 /// which raw-mode TUIs may interpret as the literal J key.
125 static let carriageReturn = "\r"
126
127 static func normalizingReturn(_ input: String) -> String {
128 switch input {
129 case "\n", "\r\n":
130 return carriageReturn
131 default:
132 return input
133 }
134 }
135}
136
122137private final class TerminalInputField: UITextField {
123138 var onDeleteBackward: (() -> Void)?
124139 var onInsert: ((String) -> Void)?
......@@ -352,7 +367,9 @@ public final class T3TerminalView: ExpoView, UITextFieldDelegate {
352367
353368 public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
354369 if !string.isEmpty {
355 emitInput(string)
370 // Some software keyboards deliver Return through this delegate instead of
371 // textFieldShouldReturn, so normalize that path too.
372 emitInput(TerminalInputSequence.normalizingReturn(string))
356373 return false
357374 }
358375
......@@ -360,7 +377,7 @@ public final class T3TerminalView: ExpoView, UITextFieldDelegate {
360377 }
361378
362379 public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
363 emitInput("\n")
380 emitInput(TerminalInputSequence.carriageReturn)
364381 textField.text = ""
365382 return false
366383 }
apps/mobile/src/features/terminal/NativeTerminalSurface.tsx+2-1
......@@ -145,7 +145,8 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter
145145 onSubmitEditing={(event) => {
146146 const text = event.nativeEvent.text;
147147 if (text.length > 0) {
148 props.onInput(`${text}\n`);
148 // Terminal Enter is CR. LF is Ctrl+J and raw-mode TUIs can treat it as J.
149 props.onInput(`${text}\r`);
149150 }
150151 }}
151152 />