From 6ccc090f0cca6548d36fc5383617e21113dc2ef7 Mon Sep 17 00:00:00 2001 From: David Montero Date: Fri, 26 Jun 2026 23:03:50 +0200 Subject: [PATCH] fix(editor): sync active file group when the active board changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After deleting the default board and adding a different one via the canvas picker, the editor kept editing the removed board's (now deleted) 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 ("compiles fine but runs the old code"). addBoard now points the editor at the new board's group when it becomes active, and removeBoard re-points it at whatever board is active afterwards. setActiveBoardId already did this; the canvas picker calls addBoard directly. Adds a regression test. --- .../__tests__/multi-board-integration.test.ts | 24 +++++++++++++++++++ frontend/src/store/useSimulatorStore.ts | 19 +++++++++++++++ 2 files changed, 43 insertions(+) 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);