debug: add mobile terminal scroll diagnostics overlay

Temporary overlay shows buffer state (normal/alternate), deltaY/deltaX,
whether our handler recognizes a scroll, and what action it takes.

Quality gates: typecheck, lint clean.
This commit is contained in:
Developer
2026-06-13 20:51:16 +00:00
parent 8f7f682a92
commit ebf5a57415
@@ -387,11 +387,38 @@ export const TerminalComponent = React.forwardRef<TerminalRef, TerminalProps>(
scrollPending = 0;
};
const isAlternateScreen = () => {
const term = termRef.current;
if (!term) return false;
return term.buffer.active === term.buffer.alternate;
};
const isAlternateScreen = () => {
const term = termRef.current;
if (!term) return false;
return term.buffer.active === term.buffer.alternate;
};
// Debug overlay for mobile scroll diagnostics
let debugOverlay: HTMLDivElement | null = null;
const showDebug = (msg: string) => {
if (!debugOverlay) {
debugOverlay = document.createElement("div");
debugOverlay.style.position = "fixed";
debugOverlay.style.bottom = "120px";
debugOverlay.style.left = "8px";
debugOverlay.style.right = "8px";
debugOverlay.style.zIndex = "9999";
debugOverlay.style.background = "rgba(0,0,0,0.8)";
debugOverlay.style.color = "#0f0";
debugOverlay.style.fontFamily = "monospace";
debugOverlay.style.fontSize = "11px";
debugOverlay.style.padding = "8px";
debugOverlay.style.borderRadius = "6px";
debugOverlay.style.pointerEvents = "none";
debugOverlay.style.whiteSpace = "pre-wrap";
debugOverlay.style.maxHeight = "120px";
debugOverlay.style.overflow = "auto";
document.body.appendChild(debugOverlay);
}
const line = `${new Date().toLocaleTimeString()} ${msg}`;
debugOverlay.textContent =
line + "\n" + debugOverlay.textContent?.split("\n").slice(0, 8).join("\n");
};
const onTouchStart = (e: TouchEvent) => {
if (e.touches.length === 1) {
@@ -406,6 +433,10 @@ export const TerminalComponent = React.forwardRef<TerminalRef, TerminalProps>(
const touch = e.touches[0];
const deltaY = startY - touch.clientY;
const deltaX = Math.abs(startX - touch.clientX);
const alternate = isAlternateScreen();
showDebug(
`move dy=${deltaY.toFixed(0)} dx=${deltaX.toFixed(0)} alt=${alternate} scrolling=${isScrolling}`,
);
// Decide early whether this is a vertical scroll gesture.
if (!isScrolling) {
@@ -418,10 +449,11 @@ export const TerminalComponent = React.forwardRef<TerminalRef, TerminalProps>(
// Take over the gesture so the page/toolbar never scrolls.
e.preventDefault();
if (isAlternateScreen()) {
if (alternate) {
// Alternate screen (tmux/vim): accumulate the swipe and
// send SGR 1006 mouse-wheel events in steps.
scrollPending += deltaY;
showDebug(`alt pending=${scrollPending.toFixed(0)}`);
flushScroll();
} else if (termRef.current) {
// Normal buffer: let xterm.js scroll its own viewport by
@@ -431,6 +463,7 @@ export const TerminalComponent = React.forwardRef<TerminalRef, TerminalProps>(
? (termRef.current.options.fontSize as number) * 1.2
: 10;
const lines = Math.round(deltaY / lineHeight);
showDebug(`normal lines=${lines}`);
if (lines !== 0) {
termRef.current.scrollLines(lines);
}