mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 02:29:33 +01:00
fix(mobile): local echo keeps painting when the viewport is parked above the bottom
Anything typed on a phone vanished whenever the terminal viewport was not scrolled fully to the bottom. Codeman parks the viewport a few rows above the bottom on purpose (scrollToLastNonEmptyLine after a tab switch, or after the keyboard drops and the terminal regrows, so trailing blank rows stay off screen), and the overlay hid itself on a bare viewportY !== baseY test even though the prompt and the cursor were on screen. The text was buffered the whole time and Enter still sent it, which is what made the keyboard look dead. The overlay now gates on whether the cursor row is inside the viewport (promptRowInViewport), in both the render path and the scroll handler, so a deep scroll into history still hides it. A buffer without cursorY keeps the old bottom-only rule. Two of Codeman's custom prompt finders made the matching mistake of treating cursorY, which xterm reports relative to baseY, as a screen row; with the gate relaxed that would have painted the text on the wrong line. Both go through cursorViewportRow now, and the Claude finder looks for its glyph from the cursor's screen row up to the top of the live screen only, since a parked viewport shows scrolled-off history whose old composer rows used to be unreachable and would anchor the overlay on the wrong line.
This commit is contained in:
1 parent
3a0cee6b90
commit
7aecbd29df
6 files changed
+199
-14
No files matched your search
@@ -177,6 +177,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Screen row of the cursor, for the local-echo prompt finders: xterm's cursorY is
|
||||
// baseY-relative, so a viewport parked above the bottom shifts it. Null when off screen.
|
||||
function cursorViewportRow(terminal) {
|
||||
try {
|
||||
const buf = terminal.buffer.active;
|
||||
const row = buf.baseY + (buf.cursorY || 0) - buf.viewportY;
|
||||
return row >= 0 && row < terminal.rows ? row : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function isTerminalQueryResponse(data) {
|
||||
return TERMINAL_QUERY_RESPONSE_PATTERN.test(data) || TERMINAL_OSC_RESPONSE_PATTERN.test(data);
|
||||
}
|
||||
@@ -250,6 +262,7 @@
|
||||
isComposerNavKey,
|
||||
classifyPredictInput,
|
||||
isCodexComposerRow,
|
||||
cursorViewportRow,
|
||||
CODEX_COMPOSER_ROW_RE,
|
||||
BRACKETED_PASTE_START,
|
||||
USER_SCROLL_STICKY_SUPPRESS_MS,
|
||||
@@ -3991,14 +4004,15 @@ Object.assign(CodemanApp.prototype, {
|
||||
if (session.mode === 'opencode') {
|
||||
// OpenCode (Bubble Tea TUI): find the ┃ border on the cursor's row.
|
||||
// The input area is "┃ <text>" — the ┃ is the anchor, offset 3 skips "┃ ".
|
||||
// We use the cursor row (cursorY) to find the right line, then scan for ┃.
|
||||
// We use the cursor's screen row to find the right line, then scan for ┃.
|
||||
this._localEchoOverlay.setPrompt({
|
||||
type: 'custom',
|
||||
offset: 3,
|
||||
find: (terminal) => {
|
||||
try {
|
||||
const buf = terminal.buffer.active;
|
||||
const row = buf.cursorY;
|
||||
const row = window.CodemanTerminalInput.cursorViewportRow(terminal);
|
||||
if (row === null) return null;
|
||||
const line = buf.getLine(buf.viewportY + row);
|
||||
if (!line) return null;
|
||||
const text = line.translateToString(true);
|
||||
@@ -4028,23 +4042,25 @@ Object.assign(CodemanApp.prototype, {
|
||||
// the viewport, while xterm's cursor still marks the editable input
|
||||
// position. Fall back to cursor coordinates so phone typing appears at
|
||||
// the terminal cursor instead of disappearing into pending state.
|
||||
// The glyph is looked for from the cursor's screen row up to the top of the
|
||||
// live screen only: rows above that are parked scrollback with old composer glyphs.
|
||||
this._localEchoOverlay.setPrompt({
|
||||
type: 'custom',
|
||||
offset: 0,
|
||||
find: (terminal) => {
|
||||
try {
|
||||
const buf = terminal.buffer.active;
|
||||
for (let row = terminal.rows - 1; row >= 0; row--) {
|
||||
const cursorRow = window.CodemanTerminalInput.cursorViewportRow(terminal);
|
||||
if (cursorRow === null) return null;
|
||||
const lowest = Math.max(0, buf.baseY - buf.viewportY);
|
||||
for (let row = cursorRow; row >= lowest; row--) {
|
||||
const line = buf.getLine(buf.viewportY + row);
|
||||
if (!line) continue;
|
||||
const text = line.translateToString(true);
|
||||
const idx = text.lastIndexOf('\u276f');
|
||||
if (idx >= 0) return { row, col: idx + 2 };
|
||||
}
|
||||
return {
|
||||
row: Math.max(0, Math.min(terminal.rows - 1, buf.cursorY)),
|
||||
col: Math.max(0, Math.min(terminal.cols - 1, buf.cursorX)),
|
||||
};
|
||||
return { row: cursorRow, col: Math.max(0, Math.min(terminal.cols - 1, buf.cursorX)) };
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user