11import { defineWebSocketHandler } from "h3" ;
2- import { getShare , registerTerminalPeer , unregisterTerminalPeer , broadcastToTerminalPeers , removeTerminal , addActiveTerminal , removeActiveTerminal } from "../utils/share" ;
2+ import { getShare , registerTerminalPeer , unregisterTerminalPeer , broadcastToTerminalPeers , removeTerminal , addActiveTerminal , removeActiveTerminal , updateTerminalPeerDimensions , recalcTerminalDimensions , setTerminalDimensions } from "../utils/share" ;
33import { createTerminalConnection } from "../utils/ssh" ;
44import type { Client } from "ssh2" ;
55
@@ -49,8 +49,10 @@ export default defineWebSocketHandler({
4949 const terminalId = `st-${ Date . now ( ) } -${ Math . random ( ) . toString ( 36 ) . slice ( 2 , 6 ) } ` ;
5050 const name = `Terminal ${ session . activeTerminals . size + 1 } ` ;
5151
52- // Subscribe the creator
53- registerTerminalPeer ( terminalId , peer ) ;
52+ // Subscribe the creator and store their dimensions
53+ const creatorDims = { cols : data . cols || 80 , rows : data . rows || 24 } ;
54+ registerTerminalPeer ( terminalId , peer , creatorDims ) ;
55+ setTerminalDimensions ( terminalId , creatorDims . cols , creatorDims . rows ) ;
5456 let subs = peerTerminals . get ( peer . id ) ;
5557 if ( ! subs ) { subs = new Set ( ) ; peerTerminals . set ( peer . id , subs ) ; }
5658 subs . add ( terminalId ) ;
@@ -99,14 +101,18 @@ export default defineWebSocketHandler({
99101 }
100102 } else if ( data . type === "resize" ) {
101103 const { terminalId, cols, rows } = data ;
102- if ( typeof terminalId !== "string" ) return ;
104+ if ( typeof terminalId !== "string" || typeof cols !== "number" || typeof rows !== "number" ) return ;
105+
106+ // Update this peer's dimensions and compute min across all peers
107+ const newMin = updateTerminalPeerDimensions ( terminalId , peer . id , cols , rows ) ;
108+ if ( ! newMin ) return ; // dimensions unchanged, no PTY resize needed
103109
104110 if ( session . mode === "relay" && session . hostRelayPeer ) {
105- session . hostRelayPeer . send ( JSON . stringify ( { type : "terminal-resize" , terminalId, cols, rows } ) ) ;
111+ session . hostRelayPeer . send ( JSON . stringify ( { type : "terminal-resize" , terminalId, cols : newMin . cols , rows : newMin . rows } ) ) ;
106112 } else {
107113 const dt = directTerminals . get ( terminalId ) ;
108- if ( dt && dt . stream && typeof cols === "number" && typeof rows === "number" ) {
109- dt . stream . setWindow ( rows , cols , rows * 16 , cols * 8 ) ;
114+ if ( dt && dt . stream ) {
115+ dt . stream . setWindow ( newMin . rows , newMin . cols , newMin . rows * 16 , newMin . cols * 8 ) ;
110116 }
111117 }
112118 } else if ( data . type === "close" ) {
@@ -132,10 +138,24 @@ export default defineWebSocketHandler({
132138} ) ;
133139
134140function cleanupPeer ( peer : any ) : void {
141+ const auth = peerAuth . get ( peer . id ) ;
135142 const subs = peerTerminals . get ( peer . id ) ;
136143 if ( subs ) {
137144 for ( const terminalId of subs ) {
138145 unregisterTerminalPeer ( terminalId , peer ) ;
146+ // Recalculate min dimensions — the leaving peer may have been the smallest
147+ const newMin = recalcTerminalDimensions ( terminalId ) ;
148+ if ( newMin && auth ) {
149+ const session = getShare ( auth . shareId ) ;
150+ if ( session ) {
151+ if ( session . mode === "relay" && session . hostRelayPeer ) {
152+ session . hostRelayPeer . send ( JSON . stringify ( { type : "terminal-resize" , terminalId, cols : newMin . cols , rows : newMin . rows } ) ) ;
153+ } else {
154+ const dt = directTerminals . get ( terminalId ) ;
155+ if ( dt && dt . stream ) dt . stream . setWindow ( newMin . rows , newMin . cols , newMin . rows * 16 , newMin . cols * 8 ) ;
156+ }
157+ }
158+ }
139159 }
140160 peerTerminals . delete ( peer . id ) ;
141161 }
0 commit comments