/** * Terminal Manager - Frontend for xterm.js terminals with HTTP polling * Uses HTTP polling to bypass WebSocket/SSL issues */ class TerminalManager { constructor() { this.terminals = new Map(); // terminalId -> { terminal, fitAddon, container, mode, polling, currentOutputIndex } this.activeTerminalId = null; this.xtermLoaded = false; this.terminalsContainer = null; this.terminalTabsContainer = null; this.debugMessages = []; this.pollingInterval = 100; // ms between polls this.pollingTimers = new Map(); // terminalId -> timer // Bind methods this.createTerminal = this.createTerminal.bind(this); this.switchToTerminal = this.switchToTerminal.bind(this); this.closeTerminal = this.closeTerminal.bind(this); this.setMode = this.setMode.bind(this); this.clearScreen = this.clearScreen.bind(this); } /** * Log debug message to both console and visual debug panel */ debugLog(category, message, data = null) { const timestamp = new Date().toLocaleTimeString(); const logEntry = `[${timestamp}] [${category}] ${message}`; // Log to console console.log(logEntry, data || ''); // Add to debug panel this.debugMessages.push({ timestamp, category, message, data }); if (this.debugMessages.length > 50) { this.debugMessages.shift(); // Keep only last 50 messages } const debugContent = document.getElementById('terminal-debug-content'); if (debugContent) { const colorMap = { 'INIT': '#4a9eff', 'HTTP': '#a78bfa', 'CMD': '#51cf66', 'ERROR': '#ff6b6b', 'READY': '#ffd43b', 'PTY': '#ffa94d', 'POLL': '#ff922b' }; const color = colorMap[category] || '#e0e0e0'; debugContent.innerHTML = this.debugMessages.map(msg => { const displayColor = colorMap[msg.category] || '#e0e0e0'; return `
No sessions found. Create a new one to get started!