mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
refactor: simplify vibe-terminal-buffer to always fit horizontally
- Remove fontSize and fitHorizontally properties as they're no longer needed - Always auto-scale font size to fit terminal width in container - Simplify dimension calculation logic - Remove unused props from session-card component - Maintain bottom-aligned terminal view with proper scaling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
dbbaaa8442
commit
faba4b1407
2 changed files with 36 additions and 45 deletions
|
|
@ -209,8 +209,6 @@ export class SessionCard extends LitElement {
|
||||||
: html`
|
: html`
|
||||||
<vibe-terminal-buffer
|
<vibe-terminal-buffer
|
||||||
.sessionId=${this.session.id}
|
.sessionId=${this.session.id}
|
||||||
.fontSize=${10}
|
|
||||||
.fitHorizontally=${true}
|
|
||||||
.pollInterval=${1000}
|
.pollInterval=${1000}
|
||||||
class="w-full h-full"
|
class="w-full h-full"
|
||||||
style="pointer-events: none;"
|
style="pointer-events: none;"
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ export class VibeTerminalBuffer extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
@property({ type: String }) sessionId = '';
|
@property({ type: String }) sessionId = '';
|
||||||
@property({ type: Number }) fontSize = 14;
|
|
||||||
@property({ type: Boolean }) fitHorizontally = false;
|
|
||||||
@property({ type: Number }) pollInterval = 1000; // Poll interval in ms
|
@property({ type: Number }) pollInterval = 1000; // Poll interval in ms
|
||||||
|
|
||||||
@state() private buffer: BufferSnapshot | null = null;
|
@state() private buffer: BufferSnapshot | null = null;
|
||||||
|
|
@ -28,7 +26,6 @@ export class VibeTerminalBuffer extends LitElement {
|
||||||
@state() private loading = false;
|
@state() private loading = false;
|
||||||
@state() private actualRows = 0;
|
@state() private actualRows = 0;
|
||||||
@state() private displayedFontSize = 14;
|
@state() private displayedFontSize = 14;
|
||||||
@state() private containerCols = 80; // Calculated columns that fit
|
|
||||||
|
|
||||||
private container: HTMLElement | null = null;
|
private container: HTMLElement | null = null;
|
||||||
private pollTimer: NodeJS.Timeout | null = null;
|
private pollTimer: NodeJS.Timeout | null = null;
|
||||||
|
|
@ -69,9 +66,6 @@ export class VibeTerminalBuffer extends LitElement {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
this.startPolling();
|
this.startPolling();
|
||||||
}
|
}
|
||||||
if (changedProperties.has('fontSize') || changedProperties.has('fitHorizontally')) {
|
|
||||||
this.calculateDimensions();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update buffer content after any render
|
// Update buffer content after any render
|
||||||
if (this.container && this.buffer) {
|
if (this.container && this.buffer) {
|
||||||
|
|
@ -94,35 +88,35 @@ export class VibeTerminalBuffer extends LitElement {
|
||||||
const containerWidth = this.container.clientWidth;
|
const containerWidth = this.container.clientWidth;
|
||||||
const containerHeight = this.container.clientHeight;
|
const containerHeight = this.container.clientHeight;
|
||||||
|
|
||||||
if (this.fitHorizontally && this.buffer) {
|
// Always fit horizontally
|
||||||
// Horizontal fitting: calculate fontSize to fit buffer.cols characters in container width
|
// Step 1: Measure container width
|
||||||
const targetCharWidth = containerWidth / this.buffer.cols;
|
// Step 2: Divide by cols to get target character width
|
||||||
|
const cols = this.buffer?.cols || 80;
|
||||||
|
const targetCharWidth = containerWidth / cols;
|
||||||
|
|
||||||
// Estimate font size needed (assuming monospace font with ~0.6 char/font ratio)
|
// Step 3: Scale font size so we can fit cols characters into the container width
|
||||||
const calculatedFontSize = targetCharWidth / 0.6;
|
// Estimate font size needed (assuming monospace font with ~0.6 char/font ratio)
|
||||||
this.displayedFontSize = Math.max(4, Math.min(32, Math.floor(calculatedFontSize)));
|
const calculatedFontSize = targetCharWidth / 0.6;
|
||||||
|
this.displayedFontSize = Math.max(4, Math.min(32, Math.floor(calculatedFontSize)));
|
||||||
|
|
||||||
// Calculate actual rows with new font size
|
console.log('calculateDimensions:', {
|
||||||
const lineHeight = this.displayedFontSize * 1.2;
|
containerWidth,
|
||||||
const newActualRows = Math.max(1, Math.floor(containerHeight / lineHeight));
|
cols,
|
||||||
|
targetCharWidth,
|
||||||
|
calculatedFontSize,
|
||||||
|
displayedFontSize: this.displayedFontSize,
|
||||||
|
});
|
||||||
|
|
||||||
if (newActualRows !== this.actualRows) {
|
// Step 4: Calculate how many lines are visible based on scaled font size
|
||||||
this.actualRows = newActualRows;
|
const lineHeight = this.displayedFontSize * 1.2;
|
||||||
this.fetchBuffer();
|
const newActualRows = Math.max(1, Math.floor(containerHeight / lineHeight));
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Normal mode: use original font size and calculate cols that fit
|
|
||||||
this.displayedFontSize = this.fontSize;
|
|
||||||
const lineHeight = this.fontSize * 1.2;
|
|
||||||
const charWidth = this.fontSize * 0.6;
|
|
||||||
|
|
||||||
const newActualRows = Math.max(1, Math.floor(containerHeight / lineHeight));
|
if (newActualRows !== this.actualRows) {
|
||||||
this.containerCols = Math.max(20, Math.floor(containerWidth / charWidth));
|
this.actualRows = newActualRows;
|
||||||
|
this.fetchBuffer();
|
||||||
if (newActualRows !== this.actualRows) {
|
} else if (this.buffer) {
|
||||||
this.actualRows = newActualRows;
|
// If rows didn't change but we have a buffer, just update the display
|
||||||
this.fetchBuffer();
|
this.requestUpdate();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,7 +156,7 @@ export class VibeTerminalBuffer extends LitElement {
|
||||||
return; // No changes
|
return; // No changes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch buffer data - let server decide the viewport
|
// Fetch buffer data - request enough lines for display
|
||||||
const lines = Math.max(this.actualRows, stats.rows);
|
const lines = Math.max(this.actualRows, stats.rows);
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/sessions/${this.sessionId}/buffer?lines=${lines}&format=json`
|
`/api/sessions/${this.sessionId}/buffer?lines=${lines}&format=json`
|
||||||
|
|
@ -176,6 +170,9 @@ export class VibeTerminalBuffer extends LitElement {
|
||||||
this.lastModified = stats.lastModified;
|
this.lastModified = stats.lastModified;
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
|
// Recalculate dimensions now that we have the actual cols
|
||||||
|
this.calculateDimensions();
|
||||||
|
|
||||||
// Request update which will trigger updated() lifecycle
|
// Request update which will trigger updated() lifecycle
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -229,22 +226,18 @@ export class VibeTerminalBuffer extends LitElement {
|
||||||
|
|
||||||
const lineHeight = this.displayedFontSize * 1.2;
|
const lineHeight = this.displayedFontSize * 1.2;
|
||||||
let html = '';
|
let html = '';
|
||||||
|
|
||||||
|
// Step 5: Draw the bottom n lines
|
||||||
let cellsToRender: BufferCell[][];
|
let cellsToRender: BufferCell[][];
|
||||||
let startIndex = 0;
|
let startIndex = 0;
|
||||||
|
|
||||||
if (this.fitHorizontally) {
|
if (this.buffer.cells.length <= this.actualRows) {
|
||||||
// In fitHorizontally mode, we show all content scaled to fit
|
// All content fits
|
||||||
cellsToRender = this.buffer.cells;
|
cellsToRender = this.buffer.cells;
|
||||||
} else {
|
} else {
|
||||||
// Show the bottom portion that fits, ensuring last non-empty line is visible
|
// Content exceeds viewport, show bottom portion
|
||||||
if (this.buffer.cells.length <= this.actualRows) {
|
startIndex = this.buffer.cells.length - this.actualRows;
|
||||||
// All content fits
|
cellsToRender = this.buffer.cells.slice(startIndex);
|
||||||
cellsToRender = this.buffer.cells;
|
|
||||||
} else {
|
|
||||||
// Content exceeds viewport, show bottom portion
|
|
||||||
startIndex = this.buffer.cells.length - this.actualRows;
|
|
||||||
cellsToRender = this.buffer.cells.slice(startIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cellsToRender.forEach((row, index) => {
|
cellsToRender.forEach((row, index) => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue