fix(ui): unbreak viz.html — OrbitControls importmap, WS URL, toast NPE (#760)

Three independent bugs were stacking to make ui/viz.html unusable from `main`:

1. Three.js r160 removed `examples/js/OrbitControls.js`, so the script-tag
   load 404'd and `new THREE.OrbitControls(...)` threw. Switch to an
   importmap that pulls the ES module build, then re-expose
   `window.THREE` and `THREE.OrbitControls` so the existing component
   modules (scene.js, body-model.js, …) keep working without a wider
   refactor.

2. The WebSocket client was hardcoded to `ws://localhost:8000/ws/pose`,
   but the sensing-server listens on `--ws-port` (8765 default, 3001 in
   the Docker image) at `/ws/sensing`. Reuse the existing
   `buildSensingWsUrl()` helper from `sensing.service.js` so port
   pairings are handled centrally, and add a `?ws=…` query-string
   override for non-standard setups. The websocket-client.js default is
   also updated to derive from `window.location` instead of the dead
   `:8000/ws/pose` literal.

3. `ToastManager.show()` called `this.container.appendChild(...)` even
   when `init()` had never been called, throwing a TypeError that
   killed the rest of page initialization. Auto-init the container
   lazily on first show (patch from issue reporter).

Closes #760.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruv
2026-05-23 10:25:08 -04:00
parent 004a63e82d
commit 35d9be9ba0
3 changed files with 37 additions and 7 deletions
+12 -2
View File
@@ -1,9 +1,19 @@
// WebSocket Client for Three.js Visualization - WiFi DensePose
// Connects to ws://localhost:8000/ws/pose and manages real-time data flow
// Default endpoint is `/ws/sensing` on the same host the page was served from.
// Callers (e.g. viz.html) usually pass an explicit `url` derived from
// `buildSensingWsUrl()` so HTTP/WS port pairings are handled centrally.
function _defaultWsUrl() {
if (typeof window === 'undefined' || !window.location) {
return 'ws://localhost:8765/ws/sensing';
}
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
return `${protocol}//${window.location.host}/ws/sensing`;
}
export class WebSocketClient {
constructor(options = {}) {
this.url = options.url || 'ws://localhost:8000/ws/pose';
this.url = options.url || _defaultWsUrl();
this.ws = null;
this.state = 'disconnected'; // disconnected, connecting, connected, error
this.isRealData = false;