Fix terminal height: fit addon now measures real container size
- Show terminal container BEFORE calling fitAddon.fit() so it can measure actual dimensions (was measuring display:none → 0 height) - Read actual terminal rows from JS after init (getDimensions) - Remove max-height:600px CSS constraint, let terminal fill viewport - Revert preRender approach that caused flickering on arrow selection - Height is now dynamic (instance property) instead of hardcoded 30
This commit is contained in:
parent
2c43e31605
commit
a6eada7473
4 changed files with 35 additions and 19 deletions
|
|
@ -592,7 +592,7 @@ public sealed class WebGameHost
|
|||
ColorSystem = ColorSystemSupport.TrueColor
|
||||
});
|
||||
bufferConsole.Profile.Width = WebTerminal.Width;
|
||||
bufferConsole.Profile.Height = WebTerminal.Height;
|
||||
bufferConsole.Profile.Height = _terminal.Height;
|
||||
|
||||
bufferConsole.Write(InventoryPanel.Render(_state, _registry, _loc, scrollOffset, selectedIndex: selectedIndex));
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public sealed class WebTerminal
|
|||
});
|
||||
|
||||
public const int Width = 120;
|
||||
public const int Height = 30;
|
||||
public int Height { get; private set; } = 30;
|
||||
|
||||
public WebTerminal(IJSRuntime js)
|
||||
{
|
||||
|
|
@ -37,12 +37,23 @@ public sealed class WebTerminal
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the xterm.js terminal in the browser.
|
||||
/// Initializes the xterm.js terminal in the browser and reads actual dimensions.
|
||||
/// </summary>
|
||||
public async Task InitAsync()
|
||||
{
|
||||
await _js.InvokeVoidAsync("terminalInterop.init");
|
||||
|
||||
// Read actual terminal dimensions after fitAddon has sized the terminal
|
||||
try
|
||||
{
|
||||
var dims = await _js.InvokeAsync<TerminalDimensions>("terminalInterop.getDimensions");
|
||||
if (dims.rows >= 30)
|
||||
Height = dims.rows;
|
||||
}
|
||||
catch { /* fallback to 30 */ }
|
||||
}
|
||||
|
||||
private record TerminalDimensions(int cols, int rows);
|
||||
|
||||
// ── Output ───────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -83,7 +94,7 @@ public sealed class WebTerminal
|
|||
ColorSystem = ColorSystemSupport.TrueColor
|
||||
});
|
||||
console.Profile.Width = Width;
|
||||
console.Profile.Height = Height;
|
||||
console.Profile.Height = _instance?.Height ?? 50;
|
||||
console.Write(renderable);
|
||||
return writer.ToString();
|
||||
}
|
||||
|
|
@ -227,6 +238,7 @@ public sealed class WebTerminal
|
|||
|
||||
while (true)
|
||||
{
|
||||
|
||||
int scrollOffset = 0;
|
||||
if (selected >= pageSize)
|
||||
scrollOffset = selected - pageSize + 1;
|
||||
|
|
@ -262,7 +274,6 @@ public sealed class WebTerminal
|
|||
console.MarkupLine("[dim] ▼ ...[/]");
|
||||
|
||||
string rendered = writer.ToString().Replace("\n", "\r\n");
|
||||
// Count actual line breaks — Split('\n').Length overcounts by 1 due to trailing newline
|
||||
int lineCount = rendered.Count(c => c == '\n');
|
||||
|
||||
await WriteAsync(rendered);
|
||||
|
|
@ -278,7 +289,6 @@ public sealed class WebTerminal
|
|||
selected = (selected + 1) % options.Count;
|
||||
break;
|
||||
case ConsoleKey.Enter:
|
||||
// Clear the rendered selection before returning
|
||||
await WriteAsync($"\x1b[{lineCount}A\x1b[J");
|
||||
return selected;
|
||||
case ConsoleKey.D1 or ConsoleKey.NumPad1: if (options.Count >= 1) { await WriteAsync($"\x1b[{lineCount}A\x1b[J"); return 0; } break;
|
||||
|
|
@ -292,7 +302,7 @@ public sealed class WebTerminal
|
|||
case ConsoleKey.D9 or ConsoleKey.NumPad9: if (options.Count >= 9) { await WriteAsync($"\x1b[{lineCount}A\x1b[J"); return 8; } break;
|
||||
}
|
||||
|
||||
// Clear and re-render
|
||||
// Clear menu before re-rendering
|
||||
await WriteAsync($"\x1b[{lineCount}A\x1b[J");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ body {
|
|||
#terminal {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 960px;
|
||||
max-height: 600px;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
/* Loading screen */
|
||||
|
|
|
|||
|
|
@ -24,12 +24,17 @@ window.terminalInterop = {
|
|||
const fitAddon = new FitAddon.FitAddon();
|
||||
term.loadAddon(fitAddon);
|
||||
|
||||
// Show terminal container BEFORE opening so fitAddon can measure real dimensions
|
||||
document.getElementById('loading').classList.add('hidden');
|
||||
document.getElementById('terminal-container').classList.add('active');
|
||||
|
||||
term.open(document.getElementById('terminal'));
|
||||
|
||||
// Fit to container, but enforce minimum dimensions for game readability
|
||||
// Fit to container, enforce minimum dimensions for game readability
|
||||
fitAddon.fit();
|
||||
if (term.cols < 120 || term.rows < 30) {
|
||||
term.resize(Math.max(term.cols, 120), Math.max(term.rows, 30));
|
||||
const minCols = 120, minRows = 30;
|
||||
if (term.cols < minCols || term.rows < minRows) {
|
||||
term.resize(Math.max(term.cols, minCols), Math.max(term.rows, minRows));
|
||||
}
|
||||
|
||||
// Forward key input to C#
|
||||
|
|
@ -40,18 +45,13 @@ window.terminalInterop = {
|
|||
// Handle resize
|
||||
window.addEventListener('resize', function () {
|
||||
fitAddon.fit();
|
||||
if (term.cols < 120 || term.rows < 30) {
|
||||
term.resize(Math.max(term.cols, 120), Math.max(term.rows, 30));
|
||||
if (term.cols < minCols || term.rows < minRows) {
|
||||
term.resize(Math.max(term.cols, minCols), Math.max(term.rows, minRows));
|
||||
}
|
||||
});
|
||||
|
||||
this.term = term;
|
||||
this.fitAddon = fitAddon;
|
||||
|
||||
// Show terminal, hide loading
|
||||
document.getElementById('loading').classList.add('hidden');
|
||||
document.getElementById('terminal-container').classList.add('active');
|
||||
|
||||
term.focus();
|
||||
},
|
||||
|
||||
|
|
@ -72,5 +72,12 @@ window.terminalInterop = {
|
|||
if (this.term) {
|
||||
this.term.focus();
|
||||
}
|
||||
},
|
||||
|
||||
getDimensions: function () {
|
||||
if (this.term) {
|
||||
return { cols: this.term.cols, rows: this.term.rows };
|
||||
}
|
||||
return { cols: 120, rows: 30 };
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue