Releases: Denjino/Horizon-View
Releases · Denjino/Horizon-View
v1.0.0
Make the live-tune (F1) hotkey rebindable from the dashboard
The settings-overlay hotkey was config-only; now it has the same
press-a-key rebind dialog as the tracking toggle. RebindHotkey takes
a `target` prop ("activate" | "settings") and routes to the matching
Rust command (rebind_hotkey / rebind_settings_hotkey, both already
present). Dashboard adds a "Change" button next to the live-tune
hotkey row in Advanced.
Kept at 1.0.0 — no version bump.
v0.1.9
v0.1.8
v0.1.7
v0.1.6
v0.1.5
Make calibration robust to MediaPipe's yaw sign convention Calibration was rejecting valid captures with "head moved the wrong way for at least one dot" even when the user followed the prompts. Two contributing bugs: 1. The spline assumed positive yaw == looking right. MediaPipe's facialTransformationMatrix output sign depends on driver and mirroring conditions, and on at least some setups it's inverted relative to that assumption. The spline then sorted samples by yaw and checked that screenX was strictly INCREASING along that order — which fails the moment the convention is flipped, because sorted yaw walks screenX from +1 down to -1. Fix: infer the sign from the first/last screenX pair and apply it transparently in both fit and evaluate. The fitter only needs the yaws to be monotonic; either direction works. 2. The calibration listener was being fed the *raw* per-frame yaw, not the One-Euro-filtered yaw. A single noisy frame at the moment of Space press could push one capture far enough off-axis to flip an adjacent pair. Now the listener receives both filtered and raw, and calibration captures the filtered value (the filter is already running every frame regardless). Error messages on the remaining genuine failure modes are sharper: duplicate yaws now say "turn your head more deliberately between dots", non-monotonic says "redo with slower, more deliberate head turns".
v0.1.4
Allow WebAssembly + workers in the packaged CSP v0.1.3 bundled MediaPipe locally but still failed to start because the packaged CSP blocked WASM compilation: CompileError: WebAssembly.instantiate() ... 'wasm-eval' is not an allowed source of script in 'script-src 'self' 'sha256-...' Root cause: I had put 'unsafe-eval' on default-src, but Tauri injects its own script-src (with hashes for its bootstrap scripts) and that directive does NOT inherit from default-src — so the keyword never applied to script execution. Same story for MediaPipe's worker, which it spawns from a blob: URL. - Set explicit script-src 'self' 'wasm-unsafe-eval' blob: — Tauri appends its sha256 hashes to our directive instead of synthesizing its own, and 'wasm-unsafe-eval' permits WebAssembly compilation without re-enabling general eval(). - Set explicit worker-src 'self' blob: for MediaPipe's worker. - Tighten everything else: drop the broad `https:` allowance from default-src (assets are local now), drop the jsdelivr/googleapis connect-src entries that were only needed before bundling.
v0.1.3
Bundle MediaPipe locally and surface real init errors Packaged WebView2 was failing to initialize the Face Landmarker when fetching the WASM/model from jsdelivr + googleapis — the error came through to our handler as a non-Error object, so the UI degraded to the unhelpful "failed to start face tracker" fallback. - scripts/setup-mediapipe.mjs runs as part of pnpm build (and pnpm dev), copies the tasks-vision WASM out of node_modules into public/ mediapipe/wasm, and downloads face_landmarker.task into the same folder. Vite then publishes the lot into dist/, so the packaged app loads everything from app:// rather than the network. - HeadLandmarker points at the local paths, tries the GPU delegate first and falls back to CPU automatically if GPU compilation throws. Either path failing now surfaces a real message instead of a swallowed exception. - Calibration's catch handler properly stringifies whatever MediaPipe threw (Error / string / object with .message / JSON) and logs the raw value to the console so we can still see it if the stringified form is opaque. Installer grows ~37 MB (WASM + model) — worth it for offline first- run and to remove a fragile remote dependency. Bump to 0.1.3.
v0.1.2
Fix CameraPreview.ready never resolving after a parent re-render The original built the readiness Promise with `useRef(new Promise(...))` and stashed the resolver in a *separate* ref captured inside the constructor. The constructor expression ran on every render and overwrote the resolver, while useRef stuck with the very first promise. So once anything in the parent (e.g. setInitStatus during calibration boot) triggered a re-render between mount and the webcam coming up, the resolver that fired was attached to a brand-new throwaway promise, and the one the caller was awaiting stayed pending forever — which manifested as calibration stuck on "Starting webcam…" even though the stream itself was visibly playing in the corner. Pair the promise and its resolver in a single lazily-initialized ref so they can't drift, and mark `resolved` so a future re-fire (e.g. deviceId change re-running the effect) is a no-op rather than calling a stale resolver.
v0.1.1
Make calibration capture diagnose its own failures
Pressing Space silently no-op'd whenever latestYawRef was still null,
which gave the user no signal that anything was wrong. There are at
least three real causes (MediaPipe model still downloading, init
exception, no face yet detected) and none of them surfaced.
- Show init phase ("Loading face tracker…" / "Waiting for your face…"
/ "Tracker ready") with a live yaw readout, so the user can see when
the pipeline is alive before pressing Space.
- Visible mini camera preview during calibration. Doubles as a sanity
check that the webcam stream is up, and avoids `display: none` on
the source <video>, which can suppress frame decoding in some
WebView2 builds.
- "Capture this point" button as a backup for Space (and disabled
until init is ready). Space presses on a not-yet-ready tracker now
flash a transient hint instead of being eaten.
- Catch and surface init errors inline rather than swallowing them.
Bump to 0.1.1 so the next tag picks this commit up.