From 1c7894e15d2d526ec45c0faec8708af4e985b579 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 18 Jun 2025 03:03:12 +0200 Subject: [PATCH] Improve mobile momentum scrolling and layout fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove console.log performance logging for cleaner output - Fix layout spacer positioning with proper flexbox structure - Improve momentum scrolling responsiveness for rapid flicks - Cancel existing momentum animations when new touch starts - Amplify initial velocity and adjust friction curves for better feel 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- web/public/tests/dom-terminal-test.html | 7 +++-- web/src/client/components/terminal.ts | 36 ++++++++++++++----------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/web/public/tests/dom-terminal-test.html b/web/public/tests/dom-terminal-test.html index 6c91d48a..50fa9b3f 100644 --- a/web/public/tests/dom-terminal-test.html +++ b/web/public/tests/dom-terminal-test.html @@ -83,13 +83,15 @@ main { flex: 1; overflow: hidden; + display: flex; + flex-direction: column; } - /* Ensure the terminal element takes full height of its container */ + /* Ensure the terminal element takes available height minus spacer */ vibe-terminal { display: block; width: 100%; - height: 100%; + flex: 1; box-sizing: border-box; font-family: 'Fira Code', monospace; } @@ -128,6 +130,7 @@ rows="40" show-controls="false"> +
diff --git a/web/src/client/components/terminal.ts b/web/src/client/components/terminal.ts index c5a7cc37..e4830643 100644 --- a/web/src/client/components/terminal.ts +++ b/web/src/client/components/terminal.ts @@ -31,6 +31,7 @@ export class Terminal extends LitElement { private scrollAccumulator = 0; private touchScrollAccumulator = 0; private isTouchActive = false; + private momentumAnimationId: number | null = null; // Operation queue for batching buffer modifications private operationQueue: (() => void)[] = []; @@ -60,9 +61,6 @@ export class Terminal extends LitElement { } const queueEnd = performance.now(); - console.log( - `Processed ${operationCount} operations in ${(queueEnd - queueStart).toFixed(2)}ms` - ); // Render once after all operations are complete this.renderBuffer(); @@ -305,6 +303,12 @@ export class Terminal extends LitElement { // Only handle touch pointers, not mouse if (e.pointerType !== 'touch' || !e.isPrimary) return; + // Cancel any existing momentum scroll when new touch starts + if (this.momentumAnimationId) { + cancelAnimationFrame(this.momentumAnimationId); + this.momentumAnimationId = null; + } + this.isTouchActive = true; isScrolling = false; pointerStartY = e.clientY; @@ -365,6 +369,11 @@ export class Terminal extends LitElement { // Add momentum scrolling if needed (only after touch scrolling) if (isScrolling && Math.abs(velocity) > 0.5) { + // Cancel any existing momentum scroll before starting new one + if (this.momentumAnimationId) { + cancelAnimationFrame(this.momentumAnimationId); + this.momentumAnimationId = null; + } this.startMomentumScroll(velocity); } }; @@ -387,18 +396,21 @@ export class Terminal extends LitElement { } private startMomentumScroll(initialVelocity: number) { - let velocity = initialVelocity * 0.8; // Scale down initial velocity for smoother feel + let velocity = initialVelocity * 1.2; // Amplify initial velocity for better flick response let accumulatedScroll = 0; let frameCount = 0; const animate = () => { // Stop when velocity becomes very small - if (Math.abs(velocity) < 0.001) return; + if (Math.abs(velocity) < 0.001) { + this.momentumAnimationId = null; + return; + } frameCount++; - // macOS-like deceleration curve - more natural feel - const friction = frameCount < 10 ? 0.98 : frameCount < 30 ? 0.96 : 0.92; + // More responsive deceleration curve for better flick feel + const friction = frameCount < 15 ? 0.985 : frameCount < 45 ? 0.97 : 0.94; // Convert velocity (pixels/ms) to pixels per frame const pixelsPerFrame = velocity * 16; // 16ms frame time @@ -416,10 +428,10 @@ export class Terminal extends LitElement { // Apply friction velocity *= friction; - requestAnimationFrame(animate); + this.momentumAnimationId = requestAnimationFrame(animate); }; - requestAnimationFrame(animate); + this.momentumAnimationId = requestAnimationFrame(animate); } private scrollViewport(deltaLines: number) { @@ -507,9 +519,6 @@ export class Terminal extends LitElement { const domUpdateTime = domUpdateEnd - domUpdateStart; const linkProcessTime = linkProcessEnd - linkProcessStart; - console.log( - `Render performance: ${totalTime.toFixed(2)}ms total (buffer: ${bufferPrepTime.toFixed(2)}ms, DOM: ${domUpdateTime.toFixed(2)}ms, links: ${linkProcessTime.toFixed(2)}ms) - ${this.actualRows} rows` - ); } private renderLine(line: IBufferLine, cell: IBufferCell, cursorCol: number = -1): string { @@ -616,9 +625,6 @@ export class Terminal extends LitElement { this.terminal.write(data, () => { const writeEnd = performance.now(); - console.log( - `XTerm write took: ${(writeEnd - writeStart).toFixed(2)}ms for ${data.length} chars` - ); }); }); }