Skip to content

feat: close the Vial feature gaps - #89

Open
HaoboGu wants to merge 7 commits into
mainfrom
vial
Open

feat: close the Vial feature gaps#89
HaoboGu wants to merge 7 commits into
mainfrom
vial

Conversation

@HaoboGu

@HaoboGu HaoboGu commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #88 (feat/donglemain) — merge that first; this PR only adds the two commits on top.

Brings the configurator up to Vial's feature surface. Everything the store already fetched but no screen offered now has an editor, in priority order:

  • Unlock ceremony — challenge-key overlay polling unlock_poll every 150 ms, held/remaining progress, persistent lock indicator in the top bar (relock included). Locked rejections now point at the unlock flow.
  • Morse (tap dance) editor — pattern→action rows with presets (tap / hold / double tap / tap-hold) and a custom step builder (≤15 steps), per-key timing profiles (decision mode, hold/gap/quick-tap timeouts, unilateral tap, flow tap; blank inherits global). Morse n keycodes join the picker's Advanced group, and the hold-tap builder gains a timing-profile selector instead of hardcoding 0xFF.
  • Key overrides (forks) — trigger + modifier/caps-light condition → two outputs; advanced: suppress list, kept modifiers, chaining.
  • Encoder editing — knobs on the board are clickable; per-direction picker that flips CW→CCW after the first assignment.
  • Matrix tester — live pressed bitmap (120 ms poll, unlock-gated with CTA), seen-key trace with coverage count, layer/WPM/LED status row.
  • Keymap — layout-variant switcher (ANSI/ISO…), default-layer star + set-default on the layer tabs.
  • Device — restart and storage-reset rows behind a confirm dialog.
  • Settings — import an exported backup; every table is validated against the live capabilities before the first write.

New store mutations (setMorse/setFork/setEncoder/setDefaultLayer/refreshMatrixState/importConfig) follow the existing optimistic-update + rollback + serialized-chain pattern.

Verification

  • svelte-check: 0 errors 0 warnings · CI=true pnpm lint (incl. clippy): clean
  • Unit tests: 132 passed (new: morse pattern codec, matrix bitmap decode, mutation optimistic/rollback/out-of-range, import validation & write-through)
  • pnpm test:qemu: 6 passed against the riscv fixture

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

Base automatically changed from feat/dongle to main August 12, 2026 14:00
setMorse, setFork, setEncoder and setDefaultLayer follow the existing
optimistic-update pattern; refreshMatrixState polls the unlock-gated
bitmap for the tester; importConfig validates a backup against the live
capabilities before writing every table and re-reading the device view.
A Locked rejection now points at the unlock flow instead of naming the
raw code.

Signed-off-by: Haobo Gu <haobogu@outlook.com>
Everything the store already fetched but no screen offered:

- Unlock ceremony: challenge-key overlay polling unlock_poll, with a
  persistent lock indicator in the top bar (relock included)
- Morse editor: pattern-to-action rows with presets and a custom
  builder, per-key timing profiles; Morse n keycodes in the picker and
  a timing-profile selector on the hold-tap builder
- Key overrides: fork editor with modifier/caps-light conditions,
  suppress list, kept modifiers and chaining
- Encoder editing: clickable knobs on the board, per-direction picker
- Matrix tester: live pressed bitmap on the board, seen-key trace,
  layer/WPM/LED status row, unlock CTA while gated
- Keymap: layout-variant switcher, default-layer star on the tabs
- Device: restart and storage-reset rows behind a confirm dialog
- Settings: import an exported backup (validated before writing)

Signed-off-by: Haobo Gu <haobogu@outlook.com>
The protocol lets get_fork answer Invalid past the live table, and
set_morse rejects writes past it — the caps maxima are only build-time
capacities. Current firmware pads every table to capacity at init, but
that is initialization behavior, not a protocol guarantee:

- fetchForks ends its scan at Invalid instead of failing the connect
- import validation compares combo/morse/fork lengths against the live
  tables rather than the maxima
- Morse n keycodes, the hold-tap profile list and the morse/fork screen
  gates size themselves from the fetched tables

Signed-off-by: Haobo Gu <haobogu@outlook.com>
…paths

Keymap and encoder entries are asserted against the values baked into
qemu/src/main.rs; fork/morse/behavior/default-layer writes round-trip
and restore; the idle matrix reads as a zeroed 32-byte bitmap; and the
table-length test documents that tables come padded to capacity, with
Invalid marking the first index past them.

Signed-off-by: Haobo Gu <haobogu@outlook.com>
The BLE dongle work (rmk-rs/rmk#1028) is merged, so the pin moves from
65df1577 to the main it landed on. The src-tauri lockfile churn beyond
the rmk crates is cargo re-resolving a lock written by an older
toolchain.

Signed-off-by: Haobo Gu <haobogu@outlook.com>
@github-actions

Copy link
Copy Markdown
Contributor

A second e2e suite connects the real keyboardStore — validation, the
serialized request chain, optimistic state and the topic pump — to the
qemu firmware and walks every feature: connect snapshot against the
fixture's known values, topic streaming, key/combo/morse/fork/encoder/
default-layer/behavior writes with restore, the macro region through
the app codec, matrix polling, the insecure lock gate, import with the
device re-read, foreign-geometry refusal, and a clean disconnect.

The qemu spawn and socket-link plumbing moves into a shared harness so
both suites boot their own fixture.

Signed-off-by: Haobo Gu <haobogu@outlook.com>
@github-actions

Copy link
Copy Markdown
Contributor

Signed-off-by: Haobo Gu <haobogu@outlook.com>
@github-actions

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant