'use strict'; const Term = (() => { let term = null; let fitAddon = null; let ws = null; let panel = null; function ensure() { if (term) return; panel = document.getElementById('terminal-panel'); term = new Terminal({ cursorBlink: true, scrollback: 2000, cols: 80, rows: 24 }); fitAddon = new FitAddon.FitAddon(); term.loadAddon(fitAddon); term.open(document.getElementById('terminal')); try { fitAddon.fit(); } catch (e) {} term.onData((d) => { if (ws && ws.readyState === WebSocket.OPEN) ws.send(d); }); } function toggle() { ensure(); if (panel.classList.contains('hidden')) { panel.classList.remove('hidden'); document.getElementById('terminal-btn').classList.add('active'); try { fitAddon.fit(); } catch (e) {} connect(); } else { panel.classList.add('hidden'); document.getElementById('terminal-btn').classList.remove('active'); disconnect(); } } function connect() { if (ws) return; if (term) term.reset(); let sock; try { sock = new WebSocket(App.terminalWs); } catch (e) { term.writeln('\r\n[cannot reach daemon terminal: ' + e.message + ']'); return; } ws = sock; sock.onmessage = (ev) => { if (typeof ev.data === 'string') term.write(ev.data); else ev.data.text().then((t) => term.write(t)); }; sock.onclose = () => { if (ws === sock) ws = null; if (term) term.writeln('\r\n[connection closed]'); }; sock.onerror = () => { try { sock.close(); } catch (e) {} }; } function disconnect() { if (ws) { try { ws.close(); } catch (e) {} ws = null; } } function isOpen() { return !!panel && !panel.classList.contains('hidden'); } function close() { if (isOpen()) toggle(); } window.addEventListener('resize', () => { if (fitAddon && panel && !panel.classList.contains('hidden')) { try { fitAddon.fit(); } catch (e) {} } }); return { toggle, close, isOpen }; })();