let sshTerm = null; let sshFit = null; let sshWS = null; let sshResizeTimer = null; function initPage8() { const el = document.getElementById("ssh-terminal"); if (!el || sshTerm) { return; } sshTerm = new Terminal({ cursorBlink: true, scrollback: 2000, fontSize: 14, convertEol: true, theme: { background: "#111111" } }); sshFit = new FitAddon.FitAddon(); sshTerm.loadAddon(sshFit); sshTerm.open(el); sshTerm.onData(data => { if (sshWS?.readyState === WebSocket.OPEN) { sshWS.send(JSON.stringify({ type: "input", data: data })); } }); connectSSH(); window.addEventListener("resize", resizeSSH); resizeSSH(); } function connectSSH() { sshWS = new WebSocket( "ws://" + location.host + "/api/ssh/ws" ); sshWS.onopen = () => { resizeSSH(); sshTerm?.focus(); }; sshWS.onmessage = e => { sshTerm?.write(e.data); }; sshWS.onclose = () => { sshWS = null; sshTerm?.write( "\r\n\x1b[33m[Connection closed]\x1b[0m\r\n" ); }; } function resizeSSH() { if (!sshFit || !sshTerm) { return; } clearTimeout(sshResizeTimer); sshResizeTimer = null; sshResizeTimer = setTimeout(() => { if (!sshTerm || !sshFit) { return; } sshFit.fit(); if (sshWS?.readyState === WebSocket.OPEN) { sshWS.send(JSON.stringify({ type: "resize", cols: sshTerm.cols, rows: sshTerm.rows })); } },100); } function exitPage8() { window.removeEventListener( "resize", resizeSSH ); clearTimeout(sshResizeTimer); if (sshWS) { sshWS.onclose = null; sshWS.close(); sshWS = null; } sshTerm?.dispose(); sshTerm = null; sshFit = null; }