Merge pull request #82 from davidmonterocrespo24/feature/auto-compile-on-play
feat: auto-compile when pressing Play if code changed or no hex loadedpull/90/head^2
commit
d44ea38dcf
|
|
@ -44,7 +44,7 @@ const BOARD_PILL_COLOR: Record<BoardKind, string> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compileLogs, setCompileLogs }: EditorToolbarProps) => {
|
export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compileLogs, setCompileLogs }: EditorToolbarProps) => {
|
||||||
const { files } = useEditorStore();
|
const { files, codeChangedSinceLastCompile, markCompiled } = useEditorStore();
|
||||||
const {
|
const {
|
||||||
boards,
|
boards,
|
||||||
activeBoardId,
|
activeBoardId,
|
||||||
|
|
@ -137,6 +137,7 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
|
||||||
compileBoardProgram(activeBoardId, program);
|
compileBoardProgram(activeBoardId, program);
|
||||||
}
|
}
|
||||||
setMessage({ type: 'success', text: 'Compiled successfully' });
|
setMessage({ type: 'success', text: 'Compiled successfully' });
|
||||||
|
markCompiled();
|
||||||
setMissingLibHint(false);
|
setMissingLibHint(false);
|
||||||
} else {
|
} else {
|
||||||
const errText = result.error || result.stderr || 'Compile failed';
|
const errText = result.error || result.stderr || 'Compile failed';
|
||||||
|
|
@ -155,24 +156,62 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRun = () => {
|
// Track whether we should auto-run after compilation completes
|
||||||
|
const autoRunAfterCompile = useRef(false);
|
||||||
|
|
||||||
|
const handleRun = async () => {
|
||||||
if (activeBoardId) {
|
if (activeBoardId) {
|
||||||
const board = boards.find((b) => b.id === activeBoardId);
|
const board = boards.find((b) => b.id === activeBoardId);
|
||||||
const isQemuBoard = board?.boardKind === 'raspberry-pi-3' || board?.boardKind === 'esp32' || board?.boardKind === 'esp32-s3';
|
const isQemuBoard = board?.boardKind === 'raspberry-pi-3' || board?.boardKind === 'esp32' || board?.boardKind === 'esp32-s3';
|
||||||
if (isQemuBoard || board?.compiledProgram) {
|
|
||||||
|
// QEMU boards don't need compilation
|
||||||
|
if (isQemuBoard) {
|
||||||
trackRunSimulation(board?.boardKind);
|
trackRunSimulation(board?.boardKind);
|
||||||
startBoard(activeBoardId);
|
startBoard(activeBoardId);
|
||||||
setMessage(null);
|
setMessage(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto-compile if no program or code changed since last compile
|
||||||
|
if (!board?.compiledProgram || codeChangedSinceLastCompile) {
|
||||||
|
autoRunAfterCompile.current = true;
|
||||||
|
await handleCompile();
|
||||||
|
// After compile, check if it succeeded and run
|
||||||
|
const updatedBoard = useSimulatorStore.getState().boards.find((b) => b.id === activeBoardId);
|
||||||
|
if (autoRunAfterCompile.current && updatedBoard?.compiledProgram) {
|
||||||
|
autoRunAfterCompile.current = false;
|
||||||
|
trackRunSimulation(updatedBoard.boardKind);
|
||||||
|
startBoard(activeBoardId);
|
||||||
|
setMessage(null);
|
||||||
|
} else {
|
||||||
|
autoRunAfterCompile.current = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trackRunSimulation(board?.boardKind);
|
||||||
|
startBoard(activeBoardId);
|
||||||
|
setMessage(null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// legacy fallback
|
|
||||||
if (compiledHex) {
|
// Legacy fallback
|
||||||
|
if (!compiledHex || codeChangedSinceLastCompile) {
|
||||||
|
autoRunAfterCompile.current = true;
|
||||||
|
await handleCompile();
|
||||||
|
const hex = useSimulatorStore.getState().compiledHex;
|
||||||
|
if (autoRunAfterCompile.current && hex) {
|
||||||
|
autoRunAfterCompile.current = false;
|
||||||
|
trackRunSimulation();
|
||||||
|
startSimulation();
|
||||||
|
setMessage(null);
|
||||||
|
} else {
|
||||||
|
autoRunAfterCompile.current = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
trackRunSimulation();
|
trackRunSimulation();
|
||||||
startSimulation();
|
startSimulation();
|
||||||
setMessage(null);
|
setMessage(null);
|
||||||
} else {
|
|
||||||
setMessage({ type: 'error', text: 'Compile first' });
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -337,9 +376,9 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
|
||||||
{/* Run */}
|
{/* Run */}
|
||||||
<button
|
<button
|
||||||
onClick={handleRun}
|
onClick={handleRun}
|
||||||
disabled={running || (!['raspberry-pi-3','esp32','esp32-s3'].includes(activeBoard?.boardKind ?? '') && !compiledHex && !activeBoard?.compiledProgram)}
|
disabled={running || compiling}
|
||||||
className="tb-btn tb-btn-run"
|
className="tb-btn tb-btn-run"
|
||||||
title="Run"
|
title="Run (auto-compiles if needed)"
|
||||||
>
|
>
|
||||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor" stroke="none">
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor" stroke="none">
|
||||||
<polygon points="5,3 19,12 5,21" />
|
<polygon points="5,3 19,12 5,21" />
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,10 @@ interface EditorState {
|
||||||
setTheme: (theme: 'vs-dark' | 'light') => void;
|
setTheme: (theme: 'vs-dark' | 'light') => void;
|
||||||
setFontSize: (size: number) => void;
|
setFontSize: (size: number) => void;
|
||||||
|
|
||||||
|
// Dirty flag — tracks whether code changed since last compilation
|
||||||
|
codeChangedSinceLastCompile: boolean;
|
||||||
|
markCompiled: () => void;
|
||||||
|
|
||||||
// Legacy compat — sets content of the active file
|
// Legacy compat — sets content of the active file
|
||||||
setCode: (code: string) => void;
|
setCode: (code: string) => void;
|
||||||
}
|
}
|
||||||
|
|
@ -108,6 +112,9 @@ export const useEditorStore = create<EditorState>((set, get) => ({
|
||||||
activeGroupFileId: { [DEFAULT_GROUP_ID]: MAIN_ID },
|
activeGroupFileId: { [DEFAULT_GROUP_ID]: MAIN_ID },
|
||||||
openGroupFileIds: { [DEFAULT_GROUP_ID]: [MAIN_ID] },
|
openGroupFileIds: { [DEFAULT_GROUP_ID]: [MAIN_ID] },
|
||||||
|
|
||||||
|
codeChangedSinceLastCompile: true,
|
||||||
|
markCompiled: () => set({ codeChangedSinceLastCompile: false }),
|
||||||
|
|
||||||
// ── File operations (legacy API — operate on active group) ──────────────
|
// ── File operations (legacy API — operate on active group) ──────────────
|
||||||
|
|
||||||
createFile: (name: string) => {
|
createFile: (name: string) => {
|
||||||
|
|
@ -178,6 +185,7 @@ export const useEditorStore = create<EditorState>((set, get) => ({
|
||||||
return {
|
return {
|
||||||
files: s.files.map(mapper),
|
files: s.files.map(mapper),
|
||||||
fileGroups: { ...s.fileGroups, [groupId]: (s.fileGroups[groupId] ?? []).map(mapper) },
|
fileGroups: { ...s.fileGroups, [groupId]: (s.fileGroups[groupId] ?? []).map(mapper) },
|
||||||
|
codeChangedSinceLastCompile: true,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue