mirror of
https://github.com/tailscale/tailscale.git
synced 2025-03-25 02:31:00 +00:00

Allows other work to be unblocked while xtermjs/xterm.js#4069 is worked through. To enable testing the popup window handling, the standalone app allows opening of SSH sessions in new windows by holding down the alt key while pressing the SSH button. Signed-off-by: Mihai Parparita <mihai@tailscale.com>
69 lines
1.6 KiB
TypeScript
69 lines
1.6 KiB
TypeScript
import { Terminal } from "xterm"
|
|
import { FitAddon } from "xterm-addon-fit"
|
|
|
|
export type SSHSessionDef = {
|
|
username: string
|
|
hostname: string
|
|
}
|
|
|
|
export function runSSHSession(
|
|
termContainerNode: HTMLDivElement,
|
|
def: SSHSessionDef,
|
|
ipn: IPN,
|
|
onDone: () => void
|
|
) {
|
|
const term = new Terminal({
|
|
cursorBlink: true,
|
|
})
|
|
const fitAddon = new FitAddon()
|
|
term.loadAddon(fitAddon)
|
|
term.open(termContainerNode)
|
|
fitAddon.fit()
|
|
|
|
let onDataHook: ((data: string) => void) | undefined
|
|
term.onData((e) => {
|
|
onDataHook?.(e)
|
|
})
|
|
|
|
term.focus()
|
|
|
|
let resizeObserver: ResizeObserver | undefined
|
|
let handleBeforeUnload: ((e: BeforeUnloadEvent) => void) | undefined
|
|
|
|
const sshSession = ipn.ssh(def.hostname, def.username, {
|
|
writeFn(input) {
|
|
term.write(input)
|
|
},
|
|
writeErrorFn(err) {
|
|
console.error(err)
|
|
term.write(err)
|
|
},
|
|
setReadFn(hook) {
|
|
onDataHook = hook
|
|
},
|
|
rows: term.rows,
|
|
cols: term.cols,
|
|
onDone() {
|
|
resizeObserver?.disconnect()
|
|
term.dispose()
|
|
if (handleBeforeUnload) {
|
|
window.removeEventListener("beforeunload", handleBeforeUnload)
|
|
}
|
|
onDone()
|
|
},
|
|
})
|
|
|
|
// Make terminal and SSH session track the size of the containing DOM node.
|
|
resizeObserver =
|
|
new termContainerNode.ownerDocument.defaultView!.ResizeObserver(() =>
|
|
fitAddon.fit()
|
|
)
|
|
resizeObserver.observe(termContainerNode)
|
|
term.onResize(({ rows, cols }) => sshSession.resize(rows, cols))
|
|
|
|
// Close the session if the user closes the window without an explicit
|
|
// exit.
|
|
handleBeforeUnload = () => sshSession.close()
|
|
window.addEventListener("beforeunload", handleBeforeUnload)
|
|
}
|