Repository navigation
Conversation
The calibration bar was display-only, so joints could only be moved with the nudge buttons. It is now a range input that moves the servo on release and is disabled while a move is in flight. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This reverts commit 2296c37.
The generic form-group range margin outranked the class selector and pushed the slider below the drawn track. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The control panel now lives in ui/ as plain HTML, CSS and JS. pio run gzips it into data/ui/, the firmware streams the page and /ui/* assets from LittleFS with Content-Encoding: gzip, and a missing filesystem image returns a 503 with upload instructions. Firmware shrinks by about 72 KB. The markup is linted with html-validate, locally and in CI. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The control panel script is split into ES modules under ui/src/ and written as modern JS. Vite bundles and minifies JS and CSS, html-minifier-terser minifies the HTML, and pio run builds the UI before gzipping it onto LittleFS. Hashed assets under /ui/assets/ are served as immutable. ESLint, Prettier and html-validate run via npm run lint in ui/. Building the firmware now needs Node 20.19+. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Prefix matching sent /animations and /tests to the robot instead of the Vite dev server. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Adds @stylistic/padding-line-between-statements and curly: all to the UI ESLint config and applies them. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Applies the standard config: modern color notation, unprefixed appearance, kebab-case LED color classes (led-r/led-g/led-b), and button state rules grouped at the end so specificity ascends through the file without changing which rule wins. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Anchoring at the end of the path missed /settings?… and /anim?…, so saves and animation requests stayed on the Vite dev server. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
/setup/servo skips the safe-range clamp, so a drag could command a large jump and make parts collide or pull cables. The nudge buttons stay the only way to move a joint during calibration; the bar shows the angle and the saved band. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…to task/extract-index-page-assets
The build stamps the web UI with the firmware version, and the firmware returns 503 naming both versions instead of serving a UI from another build. -t ota now uploads the filesystem first, waits for the robot to reboot, then uploads the firmware; -t otafs remains for recovery. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Each test loads the real index.html in jsdom, imports the UI modules and drives them against a stubbed fetch that answers like the firmware and records requests. Covers the auth gate, config saving and access token states, the servo page range hint, and the setup wizard: step order, what each step saves, step-only calibration moves and LED order validation. CI runs npm test after the lint step. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The inline page in src/http/index_page.cpp lives in ui/index.html on this branch, so the POST /play route, its name values and the talking animation are added there. The dev server proxies /play to the robot. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01VUaQRAXtYTdrXQ4C4us2V5
Vite builds ui/ into one self-contained page (vite-plugin-singlefile), and scripts/embed_ui.py gzips it into a generated header that the firmware serves with Content-Encoding: gzip. The UI always matches the firmware it ships in, so LittleFS only holds audio again: the /ui/* routes, the version stamp and check, and the filesystem-first OTA order are gone. The pre-script skips Node when ui/ is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01VUaQRAXtYTdrXQ4C4us2V5
Busy state re-enables only the controls it disabled, so the wizard no longer re-renders to undo it. Servo range changes notify the servo page and the calibration step instead of every caller refreshing both, and the servo_mins/servo_maxs format lives beside the ranges. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01VUaQRAXtYTdrXQ4C4us2V5
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
I like this direction... embedding the gzipped UI in the firmware feels like a cleaner fit for Tiny Engineer and removes the firmware/LittleFS version-coupling problem entirely. Since #60 has now been squash-merged, could you rebase this branch onto the new One small thing I noticed while reviewing the build script: Other than that, the approach looks solid to me. |
What
Alternative to #60 with the same frontend work, but the page ships inside the firmware instead of on LittleFS. Pick one of the two.
src/http/index_page.cppintoui/(ES modules, Vite, Vitest), exactly as in refactor(http): serve web UI from LittleFS, bundled with Vite #60.vite-plugin-singlefilebuilds one self-contained, minifiedindex.html.scripts/embed_ui.py(a PlatformIO pre-script) gzips it into a generated header,$BUILD_DIR/generated/web_ui.h, and the firmware serves those bytes withContent-Encoding: gzipstraight from flash./ui/*routes, no version stamp or check, and-t ota/-t otafs/ LittleFS work exactly as onmain(audio only).main.embed_ui.pyskips Node when nothing underui/changed, souploadfs,otafsand no-op builds do not rebuild the UI; an identical result does not recompileindex_page.cpp.Checks
type(scope): summarytype!:plus aBREAKING CHANGE:footer — none; routes and responses are unchangedpio runand/orpio test -e nativewhen that code changed —pio run(default,ota,expression-demo),pio test -e native,python3 scripts/test_audio_pack.py,npm run lint --prefix ui,npm test --prefix uinpm test --prefix packages/tiny-engineer-cursor/…/tiny-engineer-antigravity/…/tiny-engineer-claude-codewhen that package changed — N/A, no package changesui/index.html) +docs/api.md(and README /docs/hardware/testing.mdif the route list changed) — route list unchanged; the HTML index now lives inui/index.htmldocs/settings.md; no rawaccess_tokenin logs — no new settings;docs/settings.mdweb UI section points atui/.f3d+ exported.3mf; CERN-OHL-S;AiEmblem.3mfnot used as a branding swap — N/Ainclude/pins.h+docs/hardware/together — N/A.env, tokens, or Wi-Fi passwords in logs or screenshotsPCB (if this PR changes a board)
N/A — no board changes.