From d635ab673ce07213a74cb198856e428b18345c11 Mon Sep 17 00:00:00 2001 From: Samuel Bouchet Date: Wed, 18 Mar 2026 18:03:52 +0100 Subject: [PATCH] prepare web build --- CLAUDE.md | 12 +++++ src/OpenTheBox.Web/WebGameHost.cs | 2 +- src/OpenTheBox.Web/WebTerminal.cs | 17 ++----- src/OpenTheBox.Web/wwwroot/css/terminal.css | 7 ++- src/OpenTheBox.Web/wwwroot/index.html | 1 - .../wwwroot/js/terminal-interop.js | 50 +++++++++---------- 6 files changed, 44 insertions(+), 45 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d642a54..e188195 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,6 +35,18 @@ On Windows, use the launcher for best UTF-8 support: OpenTheBox.cmd ``` +### Web Build (itch.io) +``` +dotnet run --project src/OpenTheBox.Web # Dev local (http://localhost:5000) +dotnet publish src/OpenTheBox.Web -c Release -o builds/web # Publication +``` +Upload `builds/web/wwwroot/` sur itch.io en HTML5. + +Running locally: +``` +npx serve builds/web/wwwroot/ +``` + ## Test ``` dotnet test diff --git a/src/OpenTheBox.Web/WebGameHost.cs b/src/OpenTheBox.Web/WebGameHost.cs index 9e7fef3..aa1627d 100644 --- a/src/OpenTheBox.Web/WebGameHost.cs +++ b/src/OpenTheBox.Web/WebGameHost.cs @@ -592,7 +592,7 @@ public sealed class WebGameHost ColorSystem = ColorSystemSupport.TrueColor }); bufferConsole.Profile.Width = WebTerminal.Width; - bufferConsole.Profile.Height = _terminal.Height; + bufferConsole.Profile.Height = WebTerminal.Height; bufferConsole.Write(InventoryPanel.Render(_state, _registry, _loc, scrollOffset, selectedIndex: selectedIndex)); diff --git a/src/OpenTheBox.Web/WebTerminal.cs b/src/OpenTheBox.Web/WebTerminal.cs index e2ea27b..63a6305 100644 --- a/src/OpenTheBox.Web/WebTerminal.cs +++ b/src/OpenTheBox.Web/WebTerminal.cs @@ -28,7 +28,7 @@ public sealed class WebTerminal }); public const int Width = 120; - public int Height { get; private set; } = 30; + public const int Height = 30; public WebTerminal(IJSRuntime js) { @@ -37,24 +37,13 @@ public sealed class WebTerminal } /// - /// Initializes the xterm.js terminal in the browser and reads actual dimensions. + /// Initializes the xterm.js terminal in the browser (fixed 120x30). /// 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("terminalInterop.getDimensions"); - if (dims.rows >= 30) - Height = dims.rows; - } - catch { /* fallback to 30 */ } } - private record TerminalDimensions(int cols, int rows); - // ── Output ─────────────────────────────────────────────────────────── /// @@ -94,7 +83,7 @@ public sealed class WebTerminal ColorSystem = ColorSystemSupport.TrueColor }); console.Profile.Width = Width; - console.Profile.Height = _instance?.Height ?? 50; + console.Profile.Height = Height; console.Write(renderable); return writer.ToString(); } diff --git a/src/OpenTheBox.Web/wwwroot/css/terminal.css b/src/OpenTheBox.Web/wwwroot/css/terminal.css index 98a179d..17e1587 100644 --- a/src/OpenTheBox.Web/wwwroot/css/terminal.css +++ b/src/OpenTheBox.Web/wwwroot/css/terminal.css @@ -21,17 +21,16 @@ body { align-items: center; width: 100%; height: 100%; - padding: 8px; } #terminal-container.active { display: flex; } +/* Let xterm.js determine the natural size from 120x30 @ fontSize 16. + CSS transform scale (set by JS) shrinks it to fit smaller viewports. */ #terminal { - width: 100%; - height: 100%; - max-width: 1200px; + flex-shrink: 0; } /* Loading screen */ diff --git a/src/OpenTheBox.Web/wwwroot/index.html b/src/OpenTheBox.Web/wwwroot/index.html index 1dafac2..4f0110c 100644 --- a/src/OpenTheBox.Web/wwwroot/index.html +++ b/src/OpenTheBox.Web/wwwroot/index.html @@ -20,7 +20,6 @@ - diff --git a/src/OpenTheBox.Web/wwwroot/js/terminal-interop.js b/src/OpenTheBox.Web/wwwroot/js/terminal-interop.js index ea17324..63a5ed6 100644 --- a/src/OpenTheBox.Web/wwwroot/js/terminal-interop.js +++ b/src/OpenTheBox.Web/wwwroot/js/terminal-interop.js @@ -1,14 +1,13 @@ // Terminal interop bridge: xterm.js <-> .NET Blazor WASM window.terminalInterop = { term: null, - fitAddon: null, init: function () { const term = new Terminal({ cols: 120, rows: 30, fontFamily: "'Cascadia Mono', 'Consolas', 'Courier New', monospace", - fontSize: 14, + fontSize: 16, theme: { background: '#1a1a2e', foreground: '#e0e0e0', @@ -18,43 +17,47 @@ window.terminalInterop = { }, cursorBlink: true, allowProposedApi: true, - scrollback: 1000 + scrollback: 0 }); - const fitAddon = new FitAddon.FitAddon(); - term.loadAddon(fitAddon); - - // Show terminal container BEFORE opening so fitAddon can measure real dimensions + // Show terminal container BEFORE opening so xterm can measure document.getElementById('loading').classList.add('hidden'); document.getElementById('terminal-container').classList.add('active'); term.open(document.getElementById('terminal')); - // Fit to container, enforce minimum dimensions for game readability - fitAddon.fit(); - const minCols = 120, minRows = 30; - if (term.cols < minCols || term.rows < minRows) { - term.resize(Math.max(term.cols, minCols), Math.max(term.rows, minRows)); - } + // Scale the terminal to fit the viewport while keeping exact 120x30 + this._scaleToFit(); + window.addEventListener('resize', () => this._scaleToFit()); // Forward key input to C# term.onData(function (data) { DotNet.invokeMethodAsync('OpenTheBox.Web', 'OnTerminalInput', data); }); - // Handle resize - window.addEventListener('resize', function () { - fitAddon.fit(); - 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; term.focus(); }, + _scaleToFit: function () { + const el = document.querySelector('#terminal .xterm-screen'); + if (!el) return; + + const container = document.getElementById('terminal-container'); + const pad = 16; // padding around terminal + const maxW = container.clientWidth - pad; + const maxH = container.clientHeight - pad; + const termW = el.offsetWidth; + const termH = el.offsetHeight; + + if (termW === 0 || termH === 0) return; + + const scale = Math.min(1, maxW / termW, maxH / termH); + const wrapper = document.getElementById('terminal'); + wrapper.style.transform = scale < 1 ? `scale(${scale})` : ''; + wrapper.style.transformOrigin = 'center center'; + }, + write: function (text) { if (this.term) { this.term.write(text); @@ -75,9 +78,6 @@ window.terminalInterop = { }, getDimensions: function () { - if (this.term) { - return { cols: this.term.cols, rows: this.term.rows }; - } return { cols: 120, rows: 30 }; } };