feat(pi-family): guestSetup seam + board-branded workspace texts
Overlay QEMU-Linux boards are not Raspberry Pis: ProBoardDef.guestSetup lets a board send one shell line at the boot prompt (hostname/PS1/clear) to de-brand the generic image, sent before piBooted flips so uploads cannot interleave; the workspace start button and power-on title carry the board's own label for non raspberry-pi kinds; the compile console line uses the board label instead of 'Raspberry Pi 3B'.
This commit is contained in:
parent
7bb54e8d32
commit
55dd25eeba
|
|
@ -502,9 +502,9 @@ export const EditorToolbar = ({
|
|||
const blog = (type: CompilationLog['type'], message: string) =>
|
||||
addLog({ timestamp: new Date(), type, message, target: boardTarget });
|
||||
|
||||
// Raspberry Pi 3B doesn't need arduino-cli compilation
|
||||
// QEMU-Linux boards don't need arduino-cli compilation
|
||||
if (isPiBoardKind(kind)) {
|
||||
blog('info', 'Raspberry Pi 3B: no compilation needed — run Python scripts directly.');
|
||||
blog('info', `${boardLabel}: no compilation needed — run Python scripts directly.`);
|
||||
setMessage({ type: 'success', text: 'Ready (no compilation needed)' });
|
||||
setCompiling(false);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,15 @@ export const RaspberryPiWorkspace: React.FC<RaspberryPiWorkspaceProps> = ({ boar
|
|||
// Display the active board's real name (Pi 3B / 4B / 5 / Zero / …) instead of
|
||||
// a hardcoded "Raspberry Pi 3B" — the workspace serves the whole Pi family.
|
||||
const boardLabel = board ? boardDisplayName(board) : 'Raspberry Pi';
|
||||
// Overlay QEMU-Linux boards (piFamily kinds) are not Raspberry Pis — their
|
||||
// start button / power title must carry the board's own name.
|
||||
const isRaspberry = !board || board.boardKind.startsWith('raspberry-pi');
|
||||
const startLabel = isRaspberry
|
||||
? t('editor.pi.startPi')
|
||||
: t('editor.pi.startBoard', { board: boardLabel, defaultValue: 'Start {{board}}' });
|
||||
const powerOnTitle = isRaspberry
|
||||
? t('editor.pi.powerOnTitle')
|
||||
: t('editor.pi.powerOnBoardTitle', { board: boardLabel, defaultValue: 'Power on {{board}}' });
|
||||
|
||||
// Three display states: offline (!running) → booting (running, guest Linux
|
||||
// still coming up) → ready (running + booted shell). `running` flips on click
|
||||
|
|
@ -193,9 +202,9 @@ export const RaspberryPiWorkspace: React.FC<RaspberryPiWorkspaceProps> = ({ boar
|
|||
<button
|
||||
style={{ ...styles.toolbarBtn, color: '#4caf50', borderColor: '#4caf50' }}
|
||||
onClick={() => startBoard(boardId)}
|
||||
title={t('editor.pi.powerOnTitle')}
|
||||
title={powerOnTitle}
|
||||
>
|
||||
<PlayIcon />{t('editor.pi.startPi')}
|
||||
<PlayIcon />{startLabel}
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
|
|
@ -268,7 +277,7 @@ export const RaspberryPiWorkspace: React.FC<RaspberryPiWorkspaceProps> = ({ boar
|
|||
<div style={styles.offlineTitle}>{t('editor.pi.offlineTitle', { board: boardLabel })}</div>
|
||||
<div style={styles.offlineSubtitle}>{t('editor.pi.offlineSubtitle')}</div>
|
||||
<button style={styles.startBtn} onClick={() => startBoard(boardId)}>
|
||||
<PlayIcon />{t('editor.pi.startPi')}
|
||||
<PlayIcon />{startLabel}
|
||||
</button>
|
||||
<div style={styles.offlineNote}>
|
||||
{t('editor.pi.offlineNote1')}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ export interface ProBoardDef {
|
|||
* bridge (backend qemu WebSocket, VFS panel, boot terminal). The overlay
|
||||
* must also register a matching backend profile for the kind. */
|
||||
piFamily?: boolean;
|
||||
/** One shell line sent to the guest right after it reaches the boot
|
||||
* prompt (piFamily boards only). Lets a board de-brand the generic
|
||||
* image, e.g. set its own hostname/PS1 and clear the stock motd. */
|
||||
guestSetup?: string;
|
||||
/** Canvas renderer. Receives the placed board's props; return a React node.
|
||||
* When omitted, the canvas renders `<tag id=... style=absolute@x,y>`. */
|
||||
render?: (props: { id: string; x: number; y: number; running: boolean }) => React.ReactNode;
|
||||
|
|
|
|||
|
|
@ -1244,11 +1244,23 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
|
|||
};
|
||||
// Guest Linux finished booting (shell prompt reached). Flip piBooted so
|
||||
// the workspace swaps the "Booting…" overlay for the live terminal and
|
||||
// uploads know the shell is ready.
|
||||
// uploads know the shell is ready. Overlay boards may declare a
|
||||
// guestSetup line (hostname/PS1/clear) to de-brand the generic image;
|
||||
// it runs before piBooted flips so the VFS upload (gated on piBooted)
|
||||
// cannot interleave with it.
|
||||
bridge.onBooted = () => {
|
||||
set((s) => ({
|
||||
boards: s.boards.map((b) => (b.id === id ? { ...b, piBooted: true } : b)),
|
||||
}));
|
||||
const setup = getProBoard(boardKind)?.guestSetup;
|
||||
const flip = () =>
|
||||
set((s) => ({
|
||||
boards: s.boards.map((b) => (b.id === id ? { ...b, piBooted: true } : b)),
|
||||
}));
|
||||
if (setup) {
|
||||
void bridge
|
||||
.sendAndWaitForPrompt(setup.endsWith('\n') ? setup : setup + '\n')
|
||||
.then(flip);
|
||||
} else {
|
||||
flip();
|
||||
}
|
||||
};
|
||||
bridge.onDisconnected = () => {
|
||||
set((s) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue