fix: enable multiline paste in web terminal
Multiline pastes into the web terminal (especially into pi) were split into one prompt per line because bracketed-paste markers were not reaching the foreground app intact. - Put the host PTY into raw mode (tty.setraw) after openpty() so it acts as a pass-through pipe. The default canonical line discipline was line-buffering input, splitting multiline pastes at newlines, and mangling bracketed-paste markers before docker exec / pi could see them. The in-container PTY (docker exec -t) provides real discipline. - Route the mobile Paste button through xterm.js (term.paste) instead of sending raw clipboard text to the WebSocket, so content is wrapped in bracketed-paste markers when the app has enabled BPM. - Treat a text frame as a control message only when it is a JSON object with a known type (resize/ack/reset); otherwise forward as raw input so JSON-shaped pastes are no longer silently dropped. Quality gates: ruff, mypy (changed files), pytest unit (227 passed), tsc, eslint
This commit is contained in:
@@ -722,9 +722,13 @@ export const TerminalComponent = React.forwardRef<TerminalRef, TerminalProps>(
|
||||
const handlePaste = async () => {
|
||||
try {
|
||||
const text = await navigator.clipboard.readText();
|
||||
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
||||
wsRef.current.send(text);
|
||||
}
|
||||
// Route through xterm.js instead of sending raw text directly.
|
||||
// term.paste() wraps the content in bracketed-paste markers
|
||||
// (\e[200~...\e[201~) when the app has enabled BPM, so multiline
|
||||
// pastes arrive as a single input rather than one prompt per line.
|
||||
// It emits via onData, which the existing handler forwards to the
|
||||
// WebSocket, so the readyState check happens there.
|
||||
termRef.current?.paste(text);
|
||||
} catch {
|
||||
// Clipboard API not available
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user