/* * Das Terminal im eigenen Fenster. * * Eigener Einstiegspunkt, nicht Teil von app.js: diese Seite lädt weder * Livewire noch Chart.js, und app.js zöge beides mit — auf einer Seite, die * eine WebSocket-Verbindung und ein Terminal ist, sonst nichts. */ import { Terminal } from '@xterm/xterm' import { FitAddon } from '@xterm/addon-fit' import '@xterm/xterm/css/xterm.css' const root = document.querySelector('[data-terminal]') if (root) { const splash = root.querySelector('[data-terminal-splash]') const screen = root.querySelector('[data-terminal-screen]') const term = new Terminal({ convertEol: true, fontFamily: 'ui-monospace, monospace', fontSize: 13 }) const fit = new FitAddon() term.loadAddon(fit) const scheme = location.protocol === 'https:' ? 'wss' : 'ws' const socket = new WebSocket(`${scheme}://${location.host}/terminal/ws?t=${encodeURIComponent(root.dataset.ticket)}`) socket.binaryType = 'arraybuffer' // Der Vorspann weicht beim ERSTEN BYTE, nicht bei `onopen`. let opened = false const reveal = () => { if (opened) return opened = true splash.classList.add('hidden') screen.classList.remove('hidden') term.open(screen) fit.fit() } socket.onmessage = (event) => { reveal() term.write(new Uint8Array(event.data)) } term.onData((data) => socket.readyState === WebSocket.OPEN && socket.send(data)) socket.onclose = () => { reveal() term.write('\r\n\x1b[31m— Verbindung beendet —\x1b[0m\r\n') } socket.onerror = () => { reveal() term.write('\r\n\x1b[31m— Verbindung nicht möglich —\x1b[0m\r\n') } addEventListener('resize', () => opened && fit.fit()) }