diff --git a/frontend/src/__tests__/multi-board-integration.test.ts b/frontend/src/__tests__/multi-board-integration.test.ts index 8f420305..ccbb93d4 100644 --- a/frontend/src/__tests__/multi-board-integration.test.ts +++ b/frontend/src/__tests__/multi-board-integration.test.ts @@ -301,6 +301,30 @@ describe('useSimulatorStore — multi-board', () => { expect(boards.find((b) => b.id === id)).toBeUndefined(); }); + it('delete-all then addBoard re-points the editor file group at the new board', () => { + // Regression: deleting the default Uno and adding a different board (e.g. a + // Pico) via the canvas picker left the editor editing the deleted board's + // file group while compile read the NEW board's (default) group — so code + // typed into the editor was silently dropped and the board ran its default + // sketch. addBoard/removeBoard must keep the editor's active group in sync + // with the active board. + const sim = useSimulatorStore.getState(); + sim.boards.map((b) => b.id).forEach((bid) => sim.removeBoard(bid)); + const picoId = useSimulatorStore.getState().addBoard('raspberry-pi-pico', 0, 0); + + expect(useSimulatorStore.getState().activeBoardId).toBe(picoId); + const board = useSimulatorStore.getState().boards.find((b) => b.id === picoId)!; + expect(board.activeFileGroupId).toBe(`group-${picoId}`); + // The editor's active group must follow the active board. + expect(useEditorStore.getState().activeGroupId).toBe(board.activeFileGroupId); + + // And editing the active file lands in the group that compile reads. + const editor = useEditorStore.getState(); + editor.setFileContent(editor.activeFileId, '// PICO SKETCH MARKER'); + const groupFiles = useEditorStore.getState().getGroupFiles(board.activeFileGroupId); + expect(groupFiles.some((f) => f.content.includes('PICO SKETCH MARKER'))).toBe(true); + }); + it('setActiveBoardId switches legacy flat fields', () => { const { addBoard, setActiveBoardId } = useSimulatorStore.getState(); addBoard('arduino-mega', 0, 0); diff --git a/frontend/src/store/useSimulatorStore.ts b/frontend/src/store/useSimulatorStore.ts index 99b781f0..a60b26a4 100644 --- a/frontend/src/store/useSimulatorStore.ts +++ b/frontend/src/store/useSimulatorStore.ts @@ -1252,6 +1252,16 @@ export const useSimulatorStore = create((set, get) => { }); // Create the editor file group for this board useEditorStore.getState().createFileGroup(`group-${id}`); + // If this board is now the active one (it's the first board, or the + // previously-active board was removed), point the editor at its file + // group too. The canvas board picker calls addBoard directly WITHOUT + // setActiveBoardId (which is the only other place that syncs the editor + // group), so without this the editor keeps editing the previous/deleted + // board's group while compile reads THIS board's group — the code you + // type is silently dropped and the board runs its default sketch. + if (get().activeBoardId === id) { + useEditorStore.getState().setActiveGroup(`group-${id}`); + } // Init VFS for Raspberry Pi 3 boards if (isPiBoardKind(boardKind)) { useVfsStore.getState().initBoardVfs(id); @@ -1313,6 +1323,15 @@ export const useSimulatorStore = create((set, get) => { if (board) { useEditorStore.getState().deleteFileGroup(board.activeFileGroupId); } + // The removed board may have been the active one; activeBoardId was just + // reassigned (above) to a remaining board, or null. Re-point the editor's + // active file group at whatever board is active now, so the editor never + // keeps showing/editing the deleted board's group. + const newActiveId = get().activeBoardId; + if (newActiveId) { + const nb = get().boards.find((b) => b.id === newActiveId); + if (nb) useEditorStore.getState().setActiveGroup(nb.activeFileGroupId); + } // ── Interconnect: drop board and rebuild routes ────────────────── icUnbindBoard(boardId); icUpdateWires(get().wires);