Close terminal when connection is deleted

This commit is contained in:
Raven Scott 2024-11-28 03:07:24 -05:00
parent 9ec5bf0788
commit d60f37f2ed
2 changed files with 57 additions and 44 deletions

26
app.js
View File

@ -17,6 +17,7 @@ const duplicateContainerForm = document.getElementById('duplicate-container-form
// Global variables // Global variables
const connections = {}; const connections = {};
window.openTerminals = {};
let activePeer = null; let activePeer = null;
window.activePeer = null; // Expose to other modules window.activePeer = null; // Expose to other modules
@ -130,7 +131,6 @@ function addConnection(topicHex) {
peer.on('close', () => { peer.on('close', () => {
console.log(`[INFO] Disconnected from peer for topic: ${topicHex}`); console.log(`[INFO] Disconnected from peer for topic: ${topicHex}`);
updateConnectionStatus(topicId, false); updateConnectionStatus(topicId, false);
connections[topicId].peer = null; // Clear the peer reference
if (window.activePeer === peer) { if (window.activePeer === peer) {
window.activePeer = null; window.activePeer = null;
@ -154,6 +154,26 @@ function addConnection(topicHex) {
return; return;
} }
// Close and kill any open terminals associated with this connection
if (window.openTerminals[topicId]) {
console.log(`[INFO] Closing terminals for topic: ${topicId}`);
window.openTerminals[topicId].forEach((containerId) => {
try {
cleanUpTerminal(containerId); // Use the terminal.js cleanup logic
} catch (err) {
console.error(`[ERROR] Failed to kill terminal for container ${containerId}: ${err.message}`);
}
});
delete window.openTerminals[topicId];
}
// Hide the terminal modal if it is active
const terminalModal = document.getElementById('terminal-modal');
if (terminalModal.style.display === 'flex') {
console.log(`[INFO] Hiding terminal modal for disconnected topic: ${topicId}`);
terminalModal.style.display = 'none';
}
// Disconnect the peer and destroy the swarm // Disconnect the peer and destroy the swarm
if (connection.peer) { if (connection.peer) {
connection.peer.destroy(); connection.peer.destroy();
@ -173,11 +193,12 @@ function addConnection(topicHex) {
console.log(`[INFO] Disconnected and removed connection: ${topicId}`); console.log(`[INFO] Disconnected and removed connection: ${topicId}`);
// Reset active peer if it was the disconnected connection // Reset active peer if it was the disconnected connection
if (window.activePeer === connection.peer) {
window.activePeer = null; window.activePeer = null;
connectionTitle.textContent = 'Choose a Connection'; // Reset title connectionTitle.textContent = 'Choose a Connection'; // Reset title
dashboard.classList.add('hidden'); dashboard.classList.add('hidden');
containerList.innerHTML = ''; // Clear the container list containerList.innerHTML = ''; // Clear the container list
}
// Ensure the container list is cleared regardless of the active connection // Ensure the container list is cleared regardless of the active connection
resetContainerList(); resetContainerList();
@ -185,7 +206,6 @@ function addConnection(topicHex) {
// Refresh the connections view // Refresh the connections view
resetConnectionsView(); resetConnectionsView();
} }
// Function to reset the container list // Function to reset the container list
function resetContainerList() { function resetContainerList() {
containerList.innerHTML = ''; // Clear the existing list containerList.innerHTML = ''; // Clear the existing list

View File

@ -1,4 +1,3 @@
// terminal.js
import { Terminal } from 'xterm'; import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit'; import { FitAddon } from 'xterm-addon-fit';
@ -14,6 +13,11 @@ let activeContainerId = null; // Currently displayed containerId
// Kill Terminal button functionality // Kill Terminal button functionality
document.getElementById('kill-terminal-btn').onclick = () => { document.getElementById('kill-terminal-btn').onclick = () => {
killActiveTerminal();
};
// Kill the active terminal session
function killActiveTerminal() {
const containerId = activeContainerId; const containerId = activeContainerId;
if (containerId && terminalSessions[containerId]) { if (containerId && terminalSessions[containerId]) {
@ -23,19 +27,7 @@ document.getElementById('kill-terminal-btn').onclick = () => {
window.sendCommand('killTerminal', { containerId }); window.sendCommand('killTerminal', { containerId });
// Clean up terminal session // Clean up terminal session
const session = terminalSessions[containerId]; cleanUpTerminal(containerId);
session.xterm.dispose();
session.onDataDisposable.dispose();
if (session.resizeListener) {
window.removeEventListener('resize', session.resizeListener);
}
// Remove the terminal's container div from DOM
session.container.parentNode.removeChild(session.container);
delete terminalSessions[containerId];
// Remove from tray if exists
removeFromTray(containerId);
// Hide the terminal modal if this was the active session // Hide the terminal modal if this was the active session
if (activeContainerId === containerId) { if (activeContainerId === containerId) {
@ -45,7 +37,7 @@ document.getElementById('kill-terminal-btn').onclick = () => {
} else { } else {
console.error('[ERROR] No terminal session found to kill.'); console.error('[ERROR] No terminal session found to kill.');
} }
}; }
// Start terminal session // Start terminal session
function startTerminal(containerId, containerName) { function startTerminal(containerId, containerName) {
@ -55,10 +47,7 @@ function startTerminal(containerId, containerName) {
} }
if (terminalSessions[containerId]) { if (terminalSessions[containerId]) {
// Terminal session already exists
console.log(`[INFO] Terminal session already exists for container: ${containerId}`); console.log(`[INFO] Terminal session already exists for container: ${containerId}`);
// If terminal is minimized or not active, switch to it
if (activeContainerId !== containerId || terminalModal.style.display === 'none') { if (activeContainerId !== containerId || terminalModal.style.display === 'none') {
switchTerminal(containerId); switchTerminal(containerId);
} else { } else {
@ -67,10 +56,8 @@ function startTerminal(containerId, containerName) {
return; return;
} }
// Create new terminal session
console.log(`[INFO] Creating new terminal session for container: ${containerId}`); console.log(`[INFO] Creating new terminal session for container: ${containerId}`);
// Initialize new terminal session
const xterm = new Terminal({ const xterm = new Terminal({
cursorBlink: true, cursorBlink: true,
theme: { background: '#000000', foreground: '#ffffff' }, theme: { background: '#000000', foreground: '#ffffff' },
@ -78,21 +65,16 @@ function startTerminal(containerId, containerName) {
const fitAddon = new FitAddon(); const fitAddon = new FitAddon();
xterm.loadAddon(fitAddon); xterm.loadAddon(fitAddon);
// Create a container div for this terminal
const terminalDiv = document.createElement('div'); const terminalDiv = document.createElement('div');
terminalDiv.style.width = '100%'; terminalDiv.style.width = '100%';
terminalDiv.style.height = '100%'; terminalDiv.style.height = '100%';
terminalDiv.style.display = 'none'; // Initially hidden terminalDiv.style.display = 'none'; // Initially hidden
terminalContainer.appendChild(terminalDiv); terminalContainer.appendChild(terminalDiv);
// Open the terminal in the container div
xterm.open(terminalDiv); xterm.open(terminalDiv);
// Set up event listener for terminal input using onData
const onDataDisposable = xterm.onData((data) => { const onDataDisposable = xterm.onData((data) => {
console.log(`[DEBUG] Sending terminal input for container ${containerId}: ${data}`); console.log(`[DEBUG] Sending terminal input for container ${containerId}: ${data}`);
// Base64 encode the data
window.activePeer.write( window.activePeer.write(
JSON.stringify({ JSON.stringify({
type: 'terminalInput', type: 'terminalInput',
@ -103,7 +85,6 @@ function startTerminal(containerId, containerName) {
); );
}); });
// Store the terminal session
terminalSessions[containerId] = { terminalSessions[containerId] = {
xterm, xterm,
fitAddon, fitAddon,
@ -114,13 +95,11 @@ function startTerminal(containerId, containerName) {
container: terminalDiv, container: terminalDiv,
}; };
// Send startTerminal command to server
console.log(`[INFO] Starting terminal for container: ${containerId}`); console.log(`[INFO] Starting terminal for container: ${containerId}`);
window.activePeer.write( window.activePeer.write(
JSON.stringify({ command: 'startTerminal', args: { containerId } }) JSON.stringify({ command: 'startTerminal', args: { containerId } })
); );
// Switch to the requested terminal session
switchTerminal(containerId); switchTerminal(containerId);
} }
@ -132,39 +111,29 @@ function switchTerminal(containerId) {
return; return;
} }
// Hide the current terminal if any
if (activeContainerId && activeContainerId !== containerId) { if (activeContainerId && activeContainerId !== containerId) {
const currentSession = terminalSessions[activeContainerId]; const currentSession = terminalSessions[activeContainerId];
if (currentSession) { if (currentSession) {
// Remove resize listener for current session
if (currentSession.resizeListener) { if (currentSession.resizeListener) {
window.removeEventListener('resize', currentSession.resizeListener); window.removeEventListener('resize', currentSession.resizeListener);
currentSession.resizeListener = null; currentSession.resizeListener = null;
} }
// Hide current terminal's container
currentSession.container.style.display = 'none'; currentSession.container.style.display = 'none';
} }
} }
// Show the terminal
session.container.style.display = 'block'; session.container.style.display = 'block';
setTimeout(() => session.fitAddon.fit(), 10);
setTimeout(() => session.fitAddon.fit(), 10); // Ensure terminal fits properly after rendering
// Update modal title
terminalTitle.dataset.containerId = containerId; terminalTitle.dataset.containerId = containerId;
terminalTitle.textContent = `Container Terminal: ${session.name}`; terminalTitle.textContent = `Container Terminal: ${session.name}`;
// Show the terminal modal
terminalModal.style.display = 'flex'; terminalModal.style.display = 'flex';
activeContainerId = containerId; activeContainerId = containerId;
// Remove from tray if it exists
removeFromTray(containerId); removeFromTray(containerId);
console.log(`[INFO] Switched to terminal for container: ${containerId}`); console.log(`[INFO] Switched to terminal for container: ${containerId}`);
// Adjust resize event listener
if (session.resizeListener) { if (session.resizeListener) {
window.removeEventListener('resize', session.resizeListener); window.removeEventListener('resize', session.resizeListener);
} }
@ -187,7 +156,6 @@ function appendTerminalOutput(data, containerId, encoding) {
outputData = data; outputData = data;
} }
// Write the decoded data to the terminal
session.xterm.write(outputData); session.xterm.write(outputData);
} }
@ -199,5 +167,30 @@ function removeFromTray(containerId) {
} }
} }
// Clean up terminal session
function cleanUpTerminal(containerId) {
const session = terminalSessions[containerId];
if (session) {
session.xterm.dispose();
session.onDataDisposable.dispose();
if (session.resizeListener) {
window.removeEventListener('resize', session.resizeListener);
}
session.container.parentNode.removeChild(session.container);
delete terminalSessions[containerId];
console.log(`[INFO] Cleaned up terminal for container: ${containerId}`);
} else {
console.error(`[ERROR] No terminal session to clean up for container: ${containerId}`);
}
}
// Clean up all terminals
function cleanUpAllTerminals() {
Object.keys(terminalSessions).forEach(cleanUpTerminal);
terminalModal.style.display = 'none';
activeContainerId = null;
console.log('[INFO] All terminal sessions cleaned up.');
}
// Expose functions to app.js // Expose functions to app.js
export { startTerminal, appendTerminalOutput }; export { startTerminal, appendTerminalOutput, cleanUpAllTerminals };