feat: add VNC support with noVNC integration
- Introduced a new VNC viewer panel in the frontend, allowing users to connect to VNC sessions. - Implemented VNC connection handling with optional SSH tunneling in the backend. - Added a new SSH key manager for managing SSH keys within the terminal. - Created a trigger rules engine to monitor terminal output and trigger actions based on defined patterns. - Added CSS styles for the VNC viewer and its components. - Updated database schema to support VNC protocol in profiles. - Implemented WebSocket proxy for VNC connections to facilitate communication between the frontend and backend.
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
ExportImportUI,
|
||||
SFTPBrowser,
|
||||
SnippetLibrary,
|
||||
SSHKeyManager,
|
||||
TriggerEngine,
|
||||
stateLabel,
|
||||
} = window.NexusTerminal;
|
||||
|
||||
@@ -40,6 +42,8 @@
|
||||
this.exportImport = new ExportImportUI(this);
|
||||
this.sftp = new SFTPBrowser(this);
|
||||
this.snippets = new SnippetLibrary(this);
|
||||
this.sshKeys = new SSHKeyManager(this);
|
||||
this.triggers = new TriggerEngine(this);
|
||||
this.updateInfo = null;
|
||||
}
|
||||
|
||||
@@ -159,6 +163,12 @@
|
||||
// Incoming session data (terminal output)
|
||||
window.runtime.EventsOn("session:data", (payload) => {
|
||||
this.terminals.handleData(payload.sessionID, payload.data);
|
||||
this.tabs.markActivity(payload.sessionID);
|
||||
// Check trigger rules against decoded text
|
||||
try {
|
||||
const raw = atob(payload.data);
|
||||
this.triggers.check(payload.sessionID, raw);
|
||||
} catch (_) { /* noop */ }
|
||||
});
|
||||
|
||||
// Session state transitions (connecting → connected → reconnecting → disconnected)
|
||||
@@ -225,6 +235,7 @@
|
||||
// Session closed by backend
|
||||
window.runtime.EventsOn("session:closed", (payload) => {
|
||||
this.sftp.close(payload.sessionID);
|
||||
this.triggers.cleanup(payload.sessionID);
|
||||
this.tabs.handleSessionClosed(payload.sessionID);
|
||||
this.updateStatusBar();
|
||||
});
|
||||
@@ -259,6 +270,14 @@
|
||||
);
|
||||
});
|
||||
|
||||
// VNC WebSocket proxy ready — connect the viewer
|
||||
window.runtime.EventsOn("session:vnc:ready", (payload) => {
|
||||
window.NexusTerminal.VNCViewer.connect(
|
||||
payload.sessionID,
|
||||
payload.wsURL,
|
||||
);
|
||||
});
|
||||
|
||||
// App-wide commands from the native menu
|
||||
window.runtime.EventsOn("app:open-about", () => {
|
||||
this.settings.openTab("about");
|
||||
@@ -362,6 +381,7 @@
|
||||
this.terminals.destroyTerminal(sessionId);
|
||||
this.rawViewer.destroyViewer(sessionId);
|
||||
window.NexusTerminal.GitHubViewer.destroyViewer(sessionId);
|
||||
window.NexusTerminal.VNCViewer.destroyViewer(sessionId);
|
||||
this.state.removeSession(sessionId);
|
||||
this.tabs.removeTab(sessionId);
|
||||
this.updateStatusBar();
|
||||
@@ -509,6 +529,7 @@
|
||||
setupUI() {
|
||||
var btnEl = document.getElementById("btn-new-connection");
|
||||
this._bindClick("btn-new-connection", () => this.profileEditor.openNew());
|
||||
this._bindClick("btn-command-palette", () => this.commandPalette.toggle());
|
||||
this._bindClick("btn-settings", () => this.settings.open());
|
||||
this._bindClick("btn-import", () => this.importProfiles());
|
||||
this._bindClick("btn-export", () => this.exportProfiles());
|
||||
@@ -763,6 +784,15 @@
|
||||
profile.displayName || profile.host,
|
||||
);
|
||||
}
|
||||
} else if (profile.protocol === "vnc") {
|
||||
const container = document.getElementById(panelId);
|
||||
if (container) {
|
||||
window.NexusTerminal.VNCViewer.createViewer(
|
||||
sessionInfo.id,
|
||||
container,
|
||||
profile,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.terminals.createTerminal(sessionInfo.id, panelId, profile);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user