/* * SSH-Terminal-Baustein: xterm.js <-> /ws/ssh/{host_id}. * * F1 (Umsetzungsauftrag_Sonnet5.md Teil F.3.1): vorher ein Dokument-Singleton * (ein Skript pro Seite, feste Element-IDs). Jetzt eine Klasse * (SshTerminalSession) mit genau einer Instanz pro Sitzung: eigenes, * dynamisch gebautes DOM-Fragment (this.element), connect(), dispose(), * setActive(bool) und ein Statusrueckruf (options.onStatusChange) fuer eine * kuenftige Seitenleiste (Teil F.3: /workspace, noch nicht Teil dieser * Stufe). Die eigenstaendige Seite /terminal/{host_id} (templates/ * terminal.html) ist ab jetzt nur noch ein duenner Rahmen, der GENAU EINE * Instanz erzeugt -- keine zweite Implementierung (F.2, letzter Absatz). * * Vollbild: native Browser-Fullscreen-API auf dem Instanz-Wurzelelement * (Konzept 4.3). * Copy & Paste: xterm.js liefert Markieren-zum-Kopieren + Strg+Umschalt+V * bereits nativ. Aufgabe #11 (vom Nutzer nachtraeglich hinzugefuegt, siehe * FORTSETZUNG_Aufgabe11.md) ergaenzt zwei konkret gewuenschte Wege: * `copyOnSelect: true` kopiert eine Markierung sofort in die * System-Zwischenablage (kein Strg+C/Cmd+C mehr noetig -- Strg+C bleibt * ohne Markierung weiterhin SIGINT, xterm.js' Standardverhalten). Rechtsklick * fuegt ein: zuerst wird direkt versucht, ueber die Clipboard-API einzufuegen * (funktioniert in den meisten Chromium-Browsern, da ein Rechtsklick eine * "transiente Aktivierung" ist); schlaegt das fehl (Firefox/Safari ohne * Berechtigung, unsicherer Kontext), erscheint ersatzweise ein winziges * Kontextmenue mit einem "Einfuegen"-Eintrag -- der Klick darauf ist selbst * eine Benutzergeste und hat dadurch nochmal bessere Chancen auf die * Berechtigung (siehe _wireClipboard() unten). Keine serverseitige * Sonderbehandlung noetig, im Gegensatz zu RDP (siehe rdp.js). * Markieren mit gedrueckter Umschalttaste: xterm.js reicht Mausklicks an ein * Vollbild-Zielprogramm mit eigener Maussteuerung (tmux, vim, htop, mc, ...) * weiter, sobald dieses per ANSI-Escape-Sequenz Maus-Tracking anfordert -- * dann faengt ein normaler Linksklick+Ziehen KEINE lokale Textmarkierung * mehr ein (Standardverhalten jedes echten Terminals, kein Bug). Umschalt * (Shift)+Ziehen erzwingt die lokale Markierung trotzdem, xterm.js * unterstuetzt das nativ, ohne Zusatzcode. Als `title`-Tooltip auf * `.session-terminal` dokumentiert (siehe _buildElement()), da das sonst * leicht wie ein kaputtes Kopieren aussieht. * Farbschema: per ${themeOptions} Verbinde ...
`; return wrapper; } _cacheRefs() { const el = this.element; this.shellEl = el.querySelector(".session-shell"); this.statusEl = el.querySelector(".status"); this.terminalContainer = el.querySelector(".session-terminal"); this.fullscreenBtn = el.querySelector(".fullscreen-btn"); this.filetransferBtn = el.querySelector(".filetransfer-btn"); this.themeSelect = el.querySelector(".theme-select"); this.exitBtn = el.querySelector(".exit-btn"); this.ftOverlay = el.querySelector(".ft-overlay"); this.ftStatus = el.querySelector(".ft-status"); this.ftList = el.querySelector(".ft-list"); this.ftCloseBtn = el.querySelector(".ft-close-btn"); this.uploadRemotePathInput = el.querySelector(".ft-upload-remote-path"); this.uploadFileInput = el.querySelector(".ft-upload-file-input"); this.uploadFilenameLabel = el.querySelector(".ft-upload-filename"); this.uploadPickBtn = el.querySelector(".ft-upload-pick-btn"); this.uploadSubmitBtn = el.querySelector(".ft-upload-submit-btn"); this.downloadRemotePathInput = el.querySelector(".ft-download-remote-path"); this.downloadSubmitBtn = el.querySelector(".ft-download-submit-btn"); } _setStatus(text, isError) { this.statusEl.textContent = text; this.statusEl.classList.toggle("error", !!isError); if (this.options.onStatusChange) { try { this.options.onStatusChange(text, !!isError); } catch (_) { /* Aufrufer-Fehler duerfen die Sitzung nicht stoeren */ } } } // --- Terminal/WebSocket -------------------------------------------- _setupTerminal() { this._themeName = loadStoredThemeName(); this.term = new Terminal({ cursorBlink: true, fontFamily: "Menlo, Consolas, monospace", fontSize: 14, theme: TERMINAL_THEMES[this._themeName].theme, // Aufgabe #11: eine Markierung wird sofort in die System- // Zwischenablage kopiert -- kein zusaetzliches Strg+C/Cmd+C noetig. // Strg+C OHNE Markierung bleibt unveraendert SIGINT (xterm.js' // Standardverhalten, wird von copyOnSelect nicht beruehrt). copyOnSelect: true, }); this.fitAddon = new FitAddon.FitAddon(); this.term.loadAddon(this.fitAddon); // Bug-Fix (Live-Test, F.6/Aufgabe#11): xterm.js' Standard-DOM-Renderer // faerbt Zellen (inkl. Markierungs-Hintergrund) teils per dynamisch // erzeugtem