@@ -307,6 +307,30 @@ export function initShell(nsp: Namespace): void {
307307 socket . broadcast . emit ( 'state:active-pane' , { paneId } ) ;
308308 } ) ;
309309
310+ // ── Drag-to-reorder persistence ──────────────────────────────────────────
311+ socket . on ( 'state:reorder-panes' , ( { order } : { order : string [ ] } ) => {
312+ if ( ! Array . isArray ( order ) || order . length === 0 ) return ;
313+ // Validate every ID exists in dashboardState
314+ const paneIds = new Set ( dashboardState . panes . map ( ( p : PaneInfo ) => p . id ) ) ;
315+ if ( ! order . every ( id => typeof id === 'string' && paneIds . has ( id ) ) ) return ;
316+
317+ // Rebuild panes array in the requested order, appending any panes not in the order list
318+ const byId = new Map ( dashboardState . panes . map ( ( p : PaneInfo ) => [ p . id , p ] ) ) ;
319+ const reordered : PaneInfo [ ] = [ ] ;
320+ for ( const id of order ) {
321+ const pane = byId . get ( id ) ;
322+ if ( pane ) reordered . push ( pane ) ;
323+ }
324+ // Append any panes that weren't in the order array (e.g. from another project)
325+ for ( const p of dashboardState . panes ) {
326+ if ( ! order . includes ( p . id ) ) reordered . push ( p ) ;
327+ }
328+ dashboardState . panes = reordered ;
329+
330+ // Broadcast to other clients so they sync
331+ socket . broadcast . emit ( 'state:panes-reordered' , { order : reordered . map ( ( p : PaneInfo ) => p . id ) } ) ;
332+ } ) ;
333+
310334 // ── Disconnect ────────────────────────────────────────────────────────────
311335 socket . on ( 'disconnect' , ( ) => {
312336 console . log ( `[shell:disconnect] ${ socket . id } ` ) ;
0 commit comments