290 lines
12 KiB
HTML
290 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>RealRobots IDE</title>
|
|
<link rel="stylesheet" href="/src/style.css" />
|
|
</head>
|
|
<body>
|
|
<!-- Top toolbar -->
|
|
<header id="toolbar">
|
|
<div class="toolbar-left">
|
|
<span class="app-title">RealRobots IDE</span>
|
|
<label for="device-select" class="device-label">Device</label>
|
|
<select id="device-select" title="Target device (changes code generator and firmware)">
|
|
<option value="esp32s3">ESP32</option>
|
|
<option value="microbit">micro:bit</option>
|
|
<option value="rp2040">RP2040 (Pico)</option>
|
|
<option value="arduino_uno">Arduino Uno/Nano</option>
|
|
</select>
|
|
<button id="btn-connect" title="Connect to ESP32 via Web Serial">
|
|
<span class="icon">▶</span> Connect
|
|
</button>
|
|
<span id="connection-status" class="status-disconnected">Disconnected</span>
|
|
</div>
|
|
<div class="toolbar-actions">
|
|
<button id="btn-run" title="Upload and run code" disabled>
|
|
<span class="icon">▷</span> Run
|
|
</button>
|
|
<button id="btn-stop" title="Stop running code" disabled>
|
|
<span class="icon">■</span> Stop
|
|
</button>
|
|
<button id="btn-save" title="Save code to device as main.py" disabled>
|
|
<span class="icon">💾</span> Save
|
|
</button>
|
|
<button id="btn-load" title="Load block layout from device" disabled>
|
|
<span class="icon">📥</span> Load
|
|
</button>
|
|
<button id="btn-flash" title="Flash MicroPython firmware">
|
|
<span class="icon">⚡</span> Flash Firmware
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<main id="workspace-container">
|
|
<!-- Top row: Blockly + Projects sidebar -->
|
|
<div id="top-area">
|
|
<div id="blockly-area">
|
|
<div id="blockly-div"></div>
|
|
</div>
|
|
|
|
<!-- Customize toolbox sidebar -->
|
|
<div id="robot-panel" class="ide-panel hidden">
|
|
<div class="panel-header">
|
|
<span class="panel-title">Robot</span>
|
|
<button type="button" id="robot-panel-done" class="cust-done-btn" title="Close">Done</button>
|
|
</div>
|
|
<div class="panel-body robot-panel-body">
|
|
<div class="robot-toolbar">
|
|
<button type="button" id="robot-new" class="robot-tb-btn">New</button>
|
|
<button type="button" id="robot-open" class="robot-tb-btn">Open…</button>
|
|
<button type="button" id="robot-save" class="robot-tb-btn">Save…</button>
|
|
<button type="button" id="robot-apply" class="robot-tb-btn robot-tb-primary">Apply</button>
|
|
</div>
|
|
<button type="button" id="robot-import-ws" class="robot-full-btn">Import from workspace</button>
|
|
<div id="robot-device-note" class="robot-note"></div>
|
|
<div class="robot-add-row">
|
|
<select id="robot-add-select" class="robot-add-select" aria-label="Component to add"></select>
|
|
<button type="button" id="robot-add-btn" class="robot-tb-btn">Add</button>
|
|
</div>
|
|
<ul id="robot-component-list" class="robot-comp-list" aria-label="Components"></ul>
|
|
<div id="robot-editor" class="robot-editor"></div>
|
|
<div id="robot-status" class="robot-status" role="status"></div>
|
|
<input type="file" id="robot-file-input" accept=".json,application/json" class="robot-file-input-hidden" />
|
|
</div>
|
|
</div>
|
|
|
|
<div id="customizer-panel" class="ide-panel hidden">
|
|
<div class="panel-header">
|
|
<span class="panel-title">Customize Toolbox</span>
|
|
<button id="customizer-done" class="cust-done-btn" title="Exit customize mode">Done</button>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div class="cust-presets">
|
|
<div class="cust-preset-row">
|
|
<select id="preset-select" title="Saved presets">
|
|
<option value="">— select preset —</option>
|
|
</select>
|
|
<button id="preset-load" title="Load selected preset">Load</button>
|
|
<button id="preset-delete" class="btn-danger" title="Delete selected preset">Del</button>
|
|
</div>
|
|
<div class="cust-preset-row">
|
|
<input type="text" id="preset-name" placeholder="Preset name..." />
|
|
<button id="preset-save" title="Save current settings as preset">Save</button>
|
|
</div>
|
|
<div class="cust-preset-row">
|
|
<button id="preset-show-all" title="Show everything">Show All</button>
|
|
<button id="preset-hide-all" title="Hide everything">Hide All</button>
|
|
</div>
|
|
</div>
|
|
<div id="customizer-tree" class="customizer-tree"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Projects right sidebar -->
|
|
<div id="projects-panel" class="ide-panel collapsed">
|
|
<div class="panel-header">
|
|
<span class="panel-title">Projects</span>
|
|
<button class="panel-toggle" data-panel="projects-panel" title="Toggle panel">◂</button>
|
|
</div>
|
|
<div id="side-tools-rail" aria-label="Tool tabs">
|
|
<button id="btn-projects" class="side-rail-btn" title="Toggle Projects panel">
|
|
<span class="side-rail-label">PROJECTS</span>
|
|
<span class="side-rail-arrow" aria-hidden="true">◂</span>
|
|
</button>
|
|
<button id="btn-robot" class="side-rail-btn" title="Robot hardware (pins, apply init blocks)">
|
|
<span class="side-rail-label">ROBOT</span>
|
|
<span class="side-rail-arrow" aria-hidden="true">◂</span>
|
|
</button>
|
|
<button id="btn-customize" class="side-rail-btn" title="Show/hide toolbox categories and blocks">
|
|
<span class="side-rail-label">CUSTOMIZE</span>
|
|
<span class="side-rail-arrow" aria-hidden="true">◂</span>
|
|
</button>
|
|
<button id="btn-addons" class="side-rail-btn" title="Manage addons">
|
|
<span class="side-rail-label">ADDONS</span>
|
|
<span class="side-rail-arrow" aria-hidden="true">◂</span>
|
|
</button>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div class="proj-tab-content" id="proj-tab-browser">
|
|
<ul class="projects-list" id="browser-list"></ul>
|
|
<div class="projects-actions">
|
|
<div class="projects-name-row">
|
|
<input type="text" id="browser-save-name" placeholder="Project name..." />
|
|
<button id="browser-save-btn">Save</button>
|
|
</div>
|
|
<div class="projects-btn-row">
|
|
<button id="browser-load-btn" disabled>Load</button>
|
|
<button id="browser-download-btn" disabled>Download to computer</button>
|
|
<button id="browser-delete-btn" class="btn-danger" disabled>Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bottom panels: code preview + serial terminal -->
|
|
<div id="bottom-panels">
|
|
<div id="resize-handle-h" class="resize-handle horizontal"></div>
|
|
<div id="code-panel" class="ide-panel">
|
|
<div class="panel-header">
|
|
<span class="panel-title">Generated Code</span>
|
|
<button class="panel-toggle" data-panel="code-panel" title="Toggle panel">▾</button>
|
|
</div>
|
|
<div class="panel-body">
|
|
<pre id="code-preview"><code id="code-output"></code></pre>
|
|
</div>
|
|
</div>
|
|
<div id="terminal-panel" class="ide-panel">
|
|
<div class="panel-header">
|
|
<span class="panel-title">Serial Terminal</span>
|
|
<button class="panel-toggle" data-panel="terminal-panel" title="Toggle panel">▾</button>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div id="terminal-output"></div>
|
|
<div id="terminal-input-row">
|
|
<input type="text" id="terminal-input" placeholder="Type command..." disabled />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Flash progress overlay -->
|
|
<div id="flash-overlay" class="hidden">
|
|
<div id="flash-modal">
|
|
<h3>Flashing MicroPython Firmware</h3>
|
|
<div id="flash-log"></div>
|
|
<div id="flash-progress-bar">
|
|
<div id="flash-progress-fill"></div>
|
|
</div>
|
|
<span id="flash-progress-text">0%</span>
|
|
<button id="flash-close" class="hidden">Close</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Send code progress modal (Run / Save) -->
|
|
<div id="send-overlay" class="hidden">
|
|
<div id="send-modal">
|
|
<h3 id="send-modal-title">Sending code to device</h3>
|
|
<div id="send-progress-bar">
|
|
<div id="send-progress-fill"></div>
|
|
</div>
|
|
<span id="send-progress-text">0%</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Addons manager overlay -->
|
|
<div id="addons-overlay" class="hidden">
|
|
<div id="addons-modal">
|
|
<div class="addons-header">
|
|
<h3>Addons</h3>
|
|
<button id="addons-close" title="Close">×</button>
|
|
</div>
|
|
<p class="addons-description">Upload <code>.js</code> addon files to add new toolbox categories. Addons are saved in your browser.</p>
|
|
<div class="addons-upload-row">
|
|
<input type="file" id="addon-file-input" accept=".js" />
|
|
<button id="addon-install-btn">Install</button>
|
|
</div>
|
|
<div id="addon-status" class="addons-status"></div>
|
|
<ul id="addons-list" class="addons-list"></ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Upload .hex overlay (Arduino STK500) -->
|
|
<div id="hex-upload-overlay" class="hidden">
|
|
<div id="hex-upload-modal">
|
|
<div class="board-select-header">
|
|
<h3>Upload .hex to Arduino</h3>
|
|
<button id="hex-upload-close" title="Close">×</button>
|
|
</div>
|
|
<p class="board-select-description">Select your board type, choose a compiled <code>.hex</code> file, then click Upload. The browser will prompt you to pick a serial port.</p>
|
|
<div class="hex-upload-fields">
|
|
<label class="hex-field-label" for="hex-board-select">Board</label>
|
|
<select id="hex-board-select">
|
|
<option value="uno">Arduino Uno (115200 baud)</option>
|
|
<option value="nano">Arduino Nano — old bootloader (57600)</option>
|
|
<option value="nano_new">Arduino Nano — new bootloader (115200)</option>
|
|
</select>
|
|
<label class="hex-field-label" for="hex-file-input">.hex file</label>
|
|
<input type="file" id="hex-file-input" accept=".hex" />
|
|
</div>
|
|
<div class="board-select-actions">
|
|
<button id="hex-upload-btn">Upload</button>
|
|
</div>
|
|
<div id="hex-upload-status" class="hex-upload-status"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ESP32 firmware board picker overlay -->
|
|
<div id="esp32-flash-overlay" class="hidden">
|
|
<div id="esp32-flash-modal">
|
|
<div class="board-select-header">
|
|
<h3>Flash ESP32 MicroPython</h3>
|
|
<button id="esp32-flash-close" title="Close">×</button>
|
|
</div>
|
|
<p class="board-select-description">Choose your ESP32 chip family, then continue to flash firmware in-browser.</p>
|
|
<div class="hex-upload-fields">
|
|
<label class="hex-field-label" for="esp32-variant-select">Board family</label>
|
|
<select id="esp32-variant-select">
|
|
<option value="esp32s3">ESP32-S3</option>
|
|
<option value="esp32">ESP32 (Generic)</option>
|
|
<option value="esp32s2">ESP32-S2</option>
|
|
<option value="esp32c3">ESP32-C3</option>
|
|
</select>
|
|
</div>
|
|
<div class="board-select-actions">
|
|
<button id="esp32-flash-start">Flash</button>
|
|
</div>
|
|
<div id="esp32-flash-status" class="hex-upload-status"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- micro:bit firmware board picker overlay -->
|
|
<div id="microbit-flash-overlay" class="hidden">
|
|
<div id="microbit-flash-modal">
|
|
<div class="board-select-header">
|
|
<h3>Flash micro:bit MicroPython</h3>
|
|
<button id="microbit-flash-close" title="Close">×</button>
|
|
</div>
|
|
<p class="board-select-description">Choose your micro:bit hardware version, then continue to flash firmware.</p>
|
|
<div class="hex-upload-fields">
|
|
<label class="hex-field-label" for="microbit-variant-select">Board version</label>
|
|
<select id="microbit-variant-select">
|
|
<option value="v2">micro:bit v2</option>
|
|
<option value="v1">micro:bit v1</option>
|
|
</select>
|
|
</div>
|
|
<div class="board-select-actions">
|
|
<button id="microbit-flash-start">Flash</button>
|
|
</div>
|
|
<div id="microbit-flash-status" class="hex-upload-status"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="module" src="/src/main.js"></script>
|
|
</body>
|
|
</html>
|