Commit Graph

160 Commits

Author SHA1 Message Date
a2nr 2f689afc27 feat: implement sub-home/bab feature
- Generalize _read_md_cached() for generic file caching
- Add find_sub_home_for_lesson() and get_sub_home_data() helpers
- Add /api/bab/<folder> endpoint
- Detect sub-home in api_lesson for nav context
- Skip sub-home.md in find_lesson_file() and _parse_lesson_links()
- Add title to bab frontend page data
- Update generate_tokens.py & content_parser.py to skip sub-home.md
2026-07-27 22:01:01 +07:00
a2nr 9637740ea9 feat(quiz): add login gate, one-attempt enforcement, and exit penalty 2026-07-27 21:16:50 +07:00
a2nr 32ef89159a refactor(DeployTab): mode toggle inline in serial monitor + deploy FAB 2026-07-26 11:49:01 +07:00
a2nr bbdc53e601 refactor: playground self-contained full-viewport via svelte:head style 2026-07-24 15:54:29 +07:00
a2nr f705f1f314 fix: playground full-viewport width (override container max-width) 2026-07-24 15:41:36 +07:00
a2nr 455d449d1e fix: circuit tab full height in playground (override fixed 550px) 2026-07-24 14:03:44 +07:00
a2nr 1b2c51f72f chore: bump version to 19 for playground multi-tab 2026-07-24 13:46:18 +07:00
a2nr 589f3a148d feat: playground multi-tab (Velxio/Flowchart/Circuit/Code) with auto-save 2026-07-24 13:45:28 +07:00
a2nr 7e1139e7d1 refactor: make FlowchartTab eval button conditional on onRun prop 2026-07-24 13:44:25 +07:00
a2nr 8e89fde3c1 fix: docked editor panel height + quiz image parser + assets dir config
- fix(layout): editor-area docked mode sekarang height:70vh (sebelumnya
  max-height:85vh tanpa height, menyebabkan tab Arduino/velxio menciut
  ke 150px karena iframe tidak punya intrinsic height)
- fix(layout): tambah overflow:hidden pada velxio/flowchart/quiz panel
  untuk mencegah nested scrollable flex collapse
- feat(quiz): parser image dari 'image:' directive dan markdown ![alt](path)
  di question flashcard; konversi bare filename ke /assets/ path
- feat(assets): ASSETS_DIR derived dari CONTENT_DIR untuk support
  custom content directory (bukan hardcoded 'assets')
- fix(quiz): QuizTab container gunakan flex:1+min-height:0 (bukan height:100%)
- chore: hapus placeholder examples/assets/put_your_image.here
2026-07-21 20:50:01 +07:00
a2nr 156480b26f Merge dev → master: USB deployer get_sync fix (buffered pump)
Consolidates all dev work including the orphaned-read race fix:
- Single read-pump feeds a FIFO ByteStreamBuffer; readExact/drain/
  serial monitor consume from buffer (no orphaned reader.read()).
- DTR timing 50ms+100ms, port reuse, pre-sync drain.
- Vitest + ByteStreamBuffer unit tests (7 pass).
- APP_VERSION 18 for SW cache-bust.

Verified on CH340 (1a86:7523): INSYNC 0x14 + STK_OK 0x10
received cleanly, deploy succeeds.
2026-07-20 07:52:16 +07:00
a2nr 98adc0b860 fix(usb-deployer): review fixes — reset pumpRunning on exit, clear buffer on readExact timeout
WARN-1: pumpRunning now reset to false when the pump loop exits via
{done} or error, so future startPump() isn't a silent no-op.
WARN-3: readExact clears rxBuffer on timeout to avoid stale bytes
leaking into the next non-retried STK500 command.
2026-07-19 19:15:20 +07:00
a2nr 6f2f9c589a chore(frontend): bump APP_VERSION to 18 for SW cache-bust
Service worker evicts old caches on activate, so users always
get the new usb-deployer bundle with the read-pump fix instead
of a stale cached one.
2026-07-19 19:09:45 +07:00
a2nr 056b1a47b6 refactor(usb-deployer): serial monitor + flashBuffer + lifecycle use pump
- startSerialMonitor/setBaudRate stop+restart pump, subscribe rxBuffer.onData
- flashBuffer stops pump, reuses/reopens port, starts pump, drains before sync
- stopReaderWriter now just releases locks; cleanup stops pump first
- remove dead keepReading field
2026-07-19 19:09:10 +07:00
a2nr f7c088013a fix(usb-deployer): read from rxBuffer, kill orphaned-read race in get_sync
readExact and drainStray now consume the FIFO buffer fed by the pump
instead of calling reader.read() directly. No orphaned reader.read()
promise can swallow optiboot INSYNC/OK replies anymore. This is the
core fix for "get_sync failed after N attempts".
2026-07-19 19:06:44 +07:00
a2nr 121d592ce0 feat(usb-deployer): add read pump + start pump after pair
Single pump loop becomes the only reader.read() caller, feeding
rxBuffer. Serial monitor + readExact/drain will consume from the
buffer (next tasks). Build passes.
2026-07-19 19:05:54 +07:00
a2nr bf4b1a4932 feat(frontend): add vitest + ByteStreamBuffer FIFO for orphan-read fix
Test runner setup (vitest) plus deadline-based FIFO buffer that
becomes the single sink for serial bytes. readExact keeps
partial bytes buffered on timeout — the exact case that dropped
optiboot INSYNC/OK replies under the orphaned-reader race.
7 unit tests pass.
2026-07-19 19:03:40 +07:00
a2nr 8bb52682a3 docs(usb-deployer): document v3.2 get_sync fix (timing, drain, fail-fast) 2026-07-19 16:54:19 +07:00
a2nr 50b06df49b chore(usb-deployer): downgrade per-attempt get_sync log to DEBUG after fix 2026-07-19 16:53:20 +07:00
a2nr eb44a83dd5 fix(usb-deployer): DTR timing 50ms+100ms, CDC drain, fail-fast guard, retries 20 2026-07-19 16:49:27 +07:00
a2nr ee9563dbd7 debug(usb-deployer): log per-attempt get_sync bytes for diagnosis 2026-07-19 16:44:56 +07:00
a2nr 2a09ee77ab feat(embed): add raw HTML embed fence with bleach sanitization
- Add embed markdown fence: user pastes raw embed HTML code
  (from Canva/YouTube/Google Docs Share→Embed) into lesson markdown
  and slide content. Backend sanitizes via bleach (whitelist
  tags/attrs/styles) + checks iframe src against domain blacklist
  (SSRF prevention). Frontend renders iframe directly — no lazy
  action needed.
- Backend: _process_embed_embeds + _sanitize_embed_html in
  lesson_service.py, applied to lesson_content, exercise,
  lesson_info, and slide loop. Graceful fallback if tinycss2
  missing (CSS unsanitized but tags/attrs still stripped).
- Tests: 9 pytest cases (Canva/YouTube HTML, script stripping,
  onclick stripping, blocked domain, non-https iframe, empty,
  unchanged, dangerous style).
- Frontend: remove renderEmbedEmbeds.ts + wire-up + .generic-embed
  CSS (URL-only approach from earlier iteration, superseded).
  Keep .embed-error CSS for error messages.
- Example: update test_slides.md with raw HTML Canva embed (slide)
  + YouTube embed (body).
- Deps: bleach>=6.0.0, tinycss2>=1.2.0 in requirements.txt.
- Docs: consolidate 4 plan files into docs/06-embed-content.md.
2026-07-19 15:39:38 +07:00
a2nr 0cbac64c6f feat(frontend): Velxio iframe fullscreen + playground route + SvelteKit service worker
- VelxioTab: add allowfullscreen to Velxio editor iframe
- lesson.css: flex/shrink fixes for .velxio-iframe on mobile
- +layout.svelte: hide Navbar/Footer on /playground full-viewport route
- Add /playground route: Velxio editor iframe + DeployFAB bridge
- Migrate static sw.js to SvelteKit module service-worker.ts
2026-07-18 17:26:59 +07:00
a2nr d6bb2073ac feat: add markdown link support for lesson prerequisites
- Update lesson_service.py to parse markdown link format [title](path)
- Convert all lesson files to use markdown link format for prerequisites
- Backend now extracts slug directly from link path
- Supports both plain text and markdown link formats
2026-07-18 07:31:10 +07:00
a2nr cf3131bed3 chore: update velxio submodule — DeployProgress UI + SerialMonitor BLE toggle 2026-07-18 06:56:20 +07:00
a2nr a0fb1d80cd feat(velxio-deployer): unique device name + WiFi AP setup mode
- Add device_name module: NVS-persisted custom name with MAC-suffix
  fallback (Velxio-XXXX) so every device is uniquely identifiable
  out-of-the-box in BLE pairing dialog
- Add wifi_ap module: first-boot SoftAP (Velxio-Setup-XXXX / velxio123)
  with embedded HTTP config portal at 192.168.4.1 for renaming
- main.c: enter AP setup mode when no custom name is set
- ble_service.c: use dynamic device name from device_name_get(),
  with adv-packet length guard
- led_button.c: BOOT button long-press (5s) factory reset (erase NVS)
- sdkconfig.defaults: enable WiFi stack + set NimBLE default name

Frontend deviceName display already committed in 01f68d3.
2026-07-18 06:50:10 +07:00
a2nr f164134222 fix(usb-deployer): CH340 port reuse fix — skip reopen, single DTR, baud tracking 2026-07-17 14:35:30 +07:00
a2nr 2773bf2a83 feat(usb-deployer): double DTR reset + post-write delay for stubborn clones 2026-07-17 12:47:58 +07:00
a2nr 95a3569be9 chore: bump version to v17 2026-07-17 11:07:46 +07:00
a2nr 8adc28b745 refactor(usb-deployer): use named settle constant and fix comment 2026-07-17 10:38:40 +07:00
a2nr 852fccacdf fix(usb-deployer): rebalance sync retries/backoff for optiboot window 2026-07-17 10:37:57 +07:00
a2nr 2fd2b1b5b4 fix: register SvelteKit service-worker.js instead of static sw.js 2026-07-17 10:37:48 +07:00
a2nr 84827350af fix(usb-deployer): drain stray bytes until quiet window 2026-07-17 10:37:08 +07:00
a2nr 3d941191e3 refactor(usb-deployer): name timing constants for sync window tuning 2026-07-17 10:35:23 +07:00
a2nr 4ec5d4cb92 fix(usb-deployer): add detailed diagnostic logging for sync failures 2026-07-17 10:24:39 +07:00
a2nr 7dd8e5d522 fix(usb-deployer): preliminary get_sync robustness improvements 2026-07-17 10:23:39 +07:00
a2nr 24db01fd8d refactor: Footer.svelte imports APP_VERSION from $lib/version 2026-07-17 09:46:29 +07:00
a2nr 12725cbdad chore: bump version to v16 2026-07-17 09:26:17 +07:00
a2nr 01f68d354a fix: disable toggle during deploy, SSR guard for matchMedia, reactive isDesktop, safe deployBinary guard 2026-07-17 08:20:56 +07:00
a2nr 185fed636e feat: add BLE/USB toggle with auto-detect in DeployTab 2026-07-17 08:17:54 +07:00
a2nr 369897529d fix: harden USBHardwareDeployer — drain after timeout, async cleanup, flash error recovery, baud切换 2026-07-17 08:15:21 +07:00
a2nr f8e92875c9 feat: add USBHardwareDeployer with STK500v1 protocol via Web Serial API 2026-07-17 08:10:12 +07:00
a2nr 1b51e75ff0 feat: add HardwareDeployer interface, BLEHardwareDeployer implements it 2026-07-17 08:03:42 +07:00
a2nr 029efb7464 feat: convert Intel HEX to binary_content for AVR/Arduino Uno in velxio-compile route 2026-07-17 08:02:50 +07:00
a2nr a7c9d1c499 fix(deploy-tab): await handleOpenSerial() in deploy success path for proper error handling 2026-07-05 17:53:45 +07:00
a2nr bb19523f65 feat(deploy-tab): auto re-pair before deploy if connection lost 2026-07-05 17:49:40 +07:00
a2nr 87364da0c5 feat(deploy-fab): auto-reset Arduino when starting serial monitor 2026-07-05 17:48:44 +07:00
a2nr f6b57c08d1 feat(deploy-tab): auto-reset Arduino when starting serial monitor 2026-07-05 17:48:31 +07:00
a2nr bb113e6ff2 fix(ble-deployer): send ACK after CMD_RESET handler 2026-07-05 17:47:52 +07:00
a2nr c6c6daecbf feat(ble-deployer): add resetArduino() method for DTR pulse 2026-07-05 17:46:32 +07:00