@@ -537,10 +537,10 @@ class PaneManager {
537537 else if ( x > r . width * 0.72 ) dir = 'right' ;
538538 else if ( y < r . height * 0.28 ) dir = 'top' ;
539539 else if ( y > r . height * 0.72 ) dir = 'bottom' ;
540+ const sourcePane = parseInt ( e . dataTransfer . getData ( 'x-source-pane' ) || '-1' , 10 ) ;
540541 if ( dir ) {
541542 this . splitAt ( index , dir , sid , copy ) ;
542543 } else {
543- const sourcePane = parseInt ( e . dataTransfer . getData ( 'x-source-pane' ) || '-1' , 10 ) ;
544544 this . assignSession ( index , sid ) ;
545545 if ( ! copy && ! isNaN ( sourcePane ) && sourcePane >= 0 && sourcePane !== index ) this . removeTabFromPane ( sourcePane , sid ) ;
546546 }
@@ -752,6 +752,13 @@ class PaneManager {
752752 this . panes [ i ] . container = document . getElementById ( `tileTerminal${ i } ` ) ;
753753 }
754754 }
755+ // Reattach active sessions to their (possibly re-rendered) terminals
756+ for ( let i = 0 ; i < this . tabs . length ; i ++ ) {
757+ const t = this . tabs [ i ] ;
758+ if ( t && t . active ) {
759+ try { this . panes [ i ] ?. setSession ( t . active ) ; } catch ( _ ) { }
760+ }
761+ }
755762 }
756763
757764 removeTabFromPane ( index , sid ) {
@@ -832,99 +839,104 @@ class PaneManager {
832839 splitEdge ( direction , sid , copy , sourcePane ) {
833840 if ( direction === 'left' ) {
834841 if ( this . rows * ( this . cols + 1 ) > this . maxPanes ) return ;
835- this . cols += 1 ; this . widths = Array ( this . cols ) . fill ( 100 / this . cols ) ;
836- const newPanes = [ ] ; const newTabs = [ ] ;
837- for ( let r = 0 ; r < this . rows ; r ++ ) {
838- // empty first column
839- newPanes . push ( new ClaudePane ( newPanes . length , this . app ) ) ; newTabs . push ( { list : [ ] , active : null } ) ;
840- for ( let c = 0 ; c < this . cols - 1 ; c ++ ) {
841- const oldIdx = r * ( this . cols - 1 ) + c ;
842- newPanes . push ( this . panes [ oldIdx ] ) ; newTabs . push ( this . tabs [ oldIdx ] ) ;
843- }
844- }
845- this . panes = newPanes ; this . tabs = newTabs ; this . rebuildGrid ( ) ;
846- this . assignSession ( 0 , sid ) ;
842+ this . insertColumn ( 0 ) ;
843+ const target = 0 ; // top-left
844+ this . assignSession ( target , sid ) ;
847845 if ( ! copy && ! isNaN ( sourcePane ) && sourcePane >= 0 ) this . removeTabFromPane ( sourcePane , sid ) ;
848846 } else if ( direction === 'right' ) {
849847 if ( this . rows * ( this . cols + 1 ) > this . maxPanes ) return ;
850- this . cols += 1 ; this . widths = Array ( this . cols ) . fill ( 100 / this . cols ) ;
851- for ( let r = 0 ; r < this . rows ; r ++ ) { this . panes . push ( new ClaudePane ( this . panes . length , this . app ) ) ; this . tabs . push ( { list : [ ] , active : null } ) ; }
852- this . rebuildGrid ( ) ;
853- const target = this . cols - 1 ; this . assignSession ( target , sid ) ;
848+ this . insertColumn ( this . cols - 1 ) ;
849+ const target = this . cols - 1 ; // top-right
850+ this . assignSession ( target , sid ) ;
854851 if ( ! copy && ! isNaN ( sourcePane ) && sourcePane >= 0 ) this . removeTabFromPane ( sourcePane , sid ) ;
855852 } else if ( direction === 'top' ) {
856853 if ( ( this . rows + 1 ) * this . cols > this . maxPanes ) return ;
857- if ( this . rows === 1 ) { this . rows = 2 ; this . heights = [ 50 , 50 ] ; }
858- // prepend empty row
859- const newPanes = [ ] ; const newTabs = [ ] ;
860- for ( let c = 0 ; c < this . cols ; c ++ ) { newPanes . push ( new ClaudePane ( newPanes . length , this . app ) ) ; newTabs . push ( { list : [ ] , active : null } ) ; }
861- for ( let c = 0 ; c < this . cols ; c ++ ) { const oldIdx = c ; newPanes . push ( this . panes [ oldIdx ] ) ; newTabs . push ( this . tabs [ oldIdx ] ) ; }
862- this . panes = newPanes ; this . tabs = newTabs ; this . rebuildGrid ( ) ;
863- this . assignSession ( 0 , sid ) ;
854+ this . insertRow ( 0 ) ;
855+ const target = 0 ; // top-left
856+ this . assignSession ( target , sid ) ;
864857 if ( ! copy && ! isNaN ( sourcePane ) && sourcePane >= 0 ) this . removeTabFromPane ( sourcePane , sid ) ;
865858 } else if ( direction === 'bottom' ) {
866859 if ( ( this . rows + 1 ) * this . cols > this . maxPanes ) return ;
867- if ( this . rows === 1 ) { this . rows = 2 ; this . heights = [ 50 , 50 ] ; }
868- for ( let c = 0 ; c < this . cols ; c ++ ) { this . panes . push ( new ClaudePane ( this . panes . length , this . app ) ) ; this . tabs . push ( { list : [ ] , active : null } ) ; }
869- this . rebuildGrid ( ) ;
870- const target = ( this . rows - 1 ) * this . cols ; this . assignSession ( target , sid ) ;
860+ this . insertRow ( this . rows - 1 ) ;
861+ const target = ( this . rows - 1 ) * this . cols ; // bottom-left
862+ this . assignSession ( target , sid ) ;
871863 if ( ! copy && ! isNaN ( sourcePane ) && sourcePane >= 0 ) this . removeTabFromPane ( sourcePane , sid ) ;
872864 }
873865 }
874866
875867 // Split a specific cell in a given direction
876868 splitAt ( index , direction , sid , copy = false ) {
877- const col = index % this . cols ; const row = Math . floor ( index / this . cols ) ;
869+ const oldCols = this . cols ; const oldRows = this . rows ;
870+ const col = index % oldCols ; const row = Math . floor ( index / oldCols ) ;
878871 if ( direction === 'left' ) {
879- if ( this . rows * ( this . cols + 1 ) > this . maxPanes ) return ;
880- this . cols += 1 ; this . widths = Array ( this . cols ) . fill ( 100 / this . cols ) ;
881- const newPanes = [ ] ; const newTabs = [ ] ;
882- for ( let r = 0 ; r < this . rows ; r ++ ) {
883- for ( let c = 0 ; c < this . cols ; c ++ ) {
884- if ( c === col ) { newPanes . push ( new ClaudePane ( newPanes . length , this . app ) ) ; newTabs . push ( { list : [ ] , active : null } ) ; }
885- const oldIdx = r * ( this . cols - 1 ) + ( c > col ? c - 1 : c ) ;
886- newPanes . push ( this . panes [ oldIdx ] ) ; newTabs . push ( this . tabs [ oldIdx ] ) ;
887- }
888- }
889- this . panes = newPanes ; this . tabs = newTabs ; this . rebuildGrid ( ) ;
890- const target = row * this . cols + col ; this . assignSession ( target , sid ) ;
891- if ( ! copy ) this . removeTabFromPane ( index + 1 , sid ) ;
872+ if ( oldRows * ( oldCols + 1 ) > this . maxPanes ) return ;
873+ this . insertColumn ( col - 1 < 0 ? 0 : col - 1 ) ;
874+ const target = row * this . cols + col ;
875+ const srcAfter = row * this . cols + ( col + 1 ) ;
876+ this . assignSession ( target , sid ) ;
877+ if ( ! copy ) this . removeTabFromPane ( srcAfter , sid ) ;
892878 } else if ( direction === 'right' ) {
893- if ( this . rows * ( this . cols + 1 ) > this . maxPanes ) return ;
894- this . cols += 1 ; this . widths = Array ( this . cols ) . fill ( 100 / this . cols ) ;
895- const newPanes = [ ] ; const newTabs = [ ] ;
896- for ( let r = 0 ; r < this . rows ; r ++ ) {
897- for ( let c = 0 ; c < this . cols ; c ++ ) {
898- const oldIdx = r * ( this . cols - 1 ) + ( c <= col ? c : c - 1 ) ;
899- newPanes . push ( this . panes [ oldIdx ] ) ; newTabs . push ( this . tabs [ oldIdx ] ) ;
879+ if ( oldRows * ( oldCols + 1 ) > this . maxPanes ) return ;
880+ this . insertColumn ( col ) ;
881+ const target = row * this . cols + ( col + 1 ) ;
882+ const srcAfter = row * this . cols + col ;
883+ this . assignSession ( target , sid ) ;
884+ if ( ! copy ) this . removeTabFromPane ( srcAfter , sid ) ;
885+ } else if ( direction === 'top' ) {
886+ if ( ( oldRows + 1 ) * oldCols > this . maxPanes ) return ;
887+ this . insertRow ( row - 1 < 0 ? 0 : row - 1 ) ;
888+ const target = row * this . cols + col ;
889+ const srcAfter = ( row + 1 ) * this . cols + col ;
890+ this . assignSession ( target , sid ) ;
891+ if ( ! copy ) this . removeTabFromPane ( srcAfter , sid ) ;
892+ } else if ( direction === 'bottom' ) {
893+ if ( ( oldRows + 1 ) * oldCols > this . maxPanes ) return ;
894+ this . insertRow ( row ) ;
895+ const target = ( row + 1 ) * this . cols + col ;
896+ const srcAfter = row * this . cols + col ;
897+ this . assignSession ( target , sid ) ;
898+ if ( ! copy ) this . removeTabFromPane ( srcAfter , sid ) ;
899+ }
900+ }
901+
902+ insertColumn ( insertAfterCol ) {
903+ const oldCols = this . cols ; const rows = this . rows ;
904+ const oldPanes = this . panes . slice ( ) ; const oldTabs = this . tabs . map ( t => ( { list : [ ...( t ?. list || [ ] ) ] , active : t ?. active || null } ) ) ;
905+ const newPanes = [ ] ; const newTabs = [ ] ;
906+ for ( let r = 0 ; r < rows ; r ++ ) {
907+ for ( let c = 0 ; c < oldCols ; c ++ ) {
908+ newPanes . push ( oldPanes [ r * oldCols + c ] ) ;
909+ newTabs . push ( oldTabs [ r * oldCols + c ] ) ;
910+ if ( c === insertAfterCol ) {
911+ newPanes . push ( new ClaudePane ( 0 , this . app ) ) ;
912+ newTabs . push ( { list : [ ] , active : null } ) ;
900913 }
901914 }
902- this . panes = newPanes ; this . tabs = newTabs ; this . rebuildGrid ( ) ;
903- const target = row * this . cols + ( col + 1 ) ; this . assignSession ( target , sid ) ;
904- if ( ! copy ) this . removeTabFromPane ( index , sid ) ;
905- } else if ( direction === 'top' ) {
906- if ( ( this . rows + 1 ) * this . cols > this . maxPanes ) return ;
907- if ( this . rows === 1 ) { this . rows = 2 ; this . heights = [ 50 , 50 ] ; }
908- const newPanes = [ ] ; const newTabs = [ ] ;
909- for ( let r = 0 ; r < this . rows ; r ++ ) {
910- if ( r === row ) { for ( let c = 0 ; c < this . cols ; c ++ ) { newPanes . push ( new ClaudePane ( newPanes . length , this . app ) ) ; newTabs . push ( { list : [ ] , active : null } ) ; } }
911- for ( let c = 0 ; c < this . cols ; c ++ ) { const oldIdx = ( r > row ? r - 1 : r ) * this . cols + c ; newPanes . push ( this . panes [ oldIdx ] ) ; newTabs . push ( this . tabs [ oldIdx ] ) ; }
915+ }
916+ this . cols = oldCols + 1 ;
917+ this . widths = Array ( this . cols ) . fill ( 100 / this . cols ) ;
918+ this . panes = newPanes ; this . tabs = newTabs ;
919+ this . rebuildGrid ( ) ;
920+ }
921+
922+ insertRow ( insertAfterRow ) {
923+ if ( this . rows >= 2 ) return ; // cap rows to 2
924+ const oldRows = this . rows ; const cols = this . cols ;
925+ const oldPanes = this . panes . slice ( ) ; const oldTabs = this . tabs . map ( t => ( { list : [ ...( t ?. list || [ ] ) ] , active : t ?. active || null } ) ) ;
926+ const newPanes = [ ] ; const newTabs = [ ] ;
927+ for ( let r = 0 ; r < oldRows ; r ++ ) {
928+ for ( let c = 0 ; c < cols ; c ++ ) {
929+ newPanes . push ( oldPanes [ r * cols + c ] ) ;
930+ newTabs . push ( oldTabs [ r * cols + c ] ) ;
912931 }
913- this . panes = newPanes ; this . tabs = newTabs ; this . rebuildGrid ( ) ;
914- const target = row * this . cols + col ; this . assignSession ( target , sid ) ;
915- if ( ! copy ) this . removeTabFromPane ( index + this . cols , sid ) ;
916- } else if ( direction === 'bottom' ) {
917- if ( ( this . rows + 1 ) * this . cols > this . maxPanes ) return ;
918- if ( this . rows === 1 ) { this . rows = 2 ; this . heights = [ 50 , 50 ] ; }
919- const newPanes = [ ] ; const newTabs = [ ] ;
920- for ( let r = 0 ; r < this . rows ; r ++ ) {
921- for ( let c = 0 ; c < this . cols ; c ++ ) { const oldIdx = r * this . cols + c ; newPanes . push ( this . panes [ oldIdx ] ) ; newTabs . push ( this . tabs [ oldIdx ] ) ; }
922- if ( r === row ) { for ( let c = 0 ; c < this . cols ; c ++ ) { newPanes . push ( new ClaudePane ( newPanes . length , this . app ) ) ; newTabs . push ( { list : [ ] , active : null } ) ; } }
932+ if ( r === insertAfterRow ) {
933+ for ( let c = 0 ; c < cols ; c ++ ) { newPanes . push ( new ClaudePane ( 0 , this . app ) ) ; newTabs . push ( { list : [ ] , active : null } ) ; }
923934 }
924- this . panes = newPanes ; this . tabs = newTabs ; this . rebuildGrid ( ) ;
925- const target = ( row + 1 ) * this . cols + col ; this . assignSession ( target , sid ) ;
926- if ( ! copy ) this . removeTabFromPane ( index , sid ) ;
927935 }
936+ this . rows = oldRows + 1 ;
937+ this . heights = this . rows === 2 ? [ 50 , 50 ] : [ 100 ] ;
938+ this . panes = newPanes ; this . tabs = newTabs ;
939+ this . rebuildGrid ( ) ;
928940 }
929941
930942 openAddMenu ( index , anchorEl ) {
0 commit comments