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:
parent
004a63e82d
commit
35d9be9ba0
|
|
@ -1,9 +1,19 @@
|
||||||
// WebSocket Client for Three.js Visualization - WiFi DensePose
|
// 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 {
|
export class WebSocketClient {
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
this.url = options.url || 'ws://localhost:8000/ws/pose';
|
this.url = options.url || _defaultWsUrl();
|
||||||
this.ws = null;
|
this.ws = null;
|
||||||
this.state = 'disconnected'; // disconnected, connecting, connected, error
|
this.state = 'disconnected'; // disconnected, connecting, connected, error
|
||||||
this.isRealData = false;
|
this.isRealData = false;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ export class ToastManager {
|
||||||
action = null
|
action = null
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
|
if (!this.container) this.init();
|
||||||
|
|
||||||
const id = ++this.idCounter;
|
const id = ++this.idCounter;
|
||||||
const toast = document.createElement('div');
|
const toast = document.createElement('div');
|
||||||
toast.className = `toast toast-${type}`;
|
toast.className = `toast toast-${type}`;
|
||||||
|
|
|
||||||
28
ui/viz.html
28
ui/viz.html
|
|
@ -84,9 +84,23 @@
|
||||||
<div id="stats-container"></div>
|
<div id="stats-container"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Three.js and OrbitControls from CDN -->
|
<!-- Three.js r160 dropped examples/js/. Load via importmap and expose
|
||||||
<script src="https://unpkg.com/three@0.160.0/build/three.min.js"></script>
|
THREE + OrbitControls as globals so the existing component modules
|
||||||
<script src="https://unpkg.com/three@0.160.0/examples/js/controls/OrbitControls.js"></script>
|
(scene.js, body-model.js, …) keep working without an audit. -->
|
||||||
|
<script type="importmap">
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"three": "https://unpkg.com/three@0.160.0/build/three.module.js",
|
||||||
|
"three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="module">
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
||||||
|
window.THREE = THREE;
|
||||||
|
THREE.OrbitControls = OrbitControls;
|
||||||
|
</script>
|
||||||
<!-- Stats.js for performance monitoring -->
|
<!-- Stats.js for performance monitoring -->
|
||||||
<script src="https://unpkg.com/stats.js@0.17.0/build/stats.min.js"></script>
|
<script src="https://unpkg.com/stats.js@0.17.0/build/stats.min.js"></script>
|
||||||
|
|
||||||
|
|
@ -100,6 +114,7 @@
|
||||||
import { DashboardHUD } from './components/dashboard-hud.js';
|
import { DashboardHUD } from './components/dashboard-hud.js';
|
||||||
import { WebSocketClient } from './services/websocket-client.js';
|
import { WebSocketClient } from './services/websocket-client.js';
|
||||||
import { DataProcessor } from './services/data-processor.js';
|
import { DataProcessor } from './services/data-processor.js';
|
||||||
|
import { buildSensingWsUrl } from './services/sensing.service.js';
|
||||||
|
|
||||||
// -- Application State --
|
// -- Application State --
|
||||||
const state = {
|
const state = {
|
||||||
|
|
@ -175,9 +190,12 @@
|
||||||
state.stats = initStats();
|
state.stats = initStats();
|
||||||
setLoadingProgress(85, 'Connecting to server...');
|
setLoadingProgress(85, 'Connecting to server...');
|
||||||
|
|
||||||
// 8. WebSocket client
|
// 8. WebSocket client — derive URL from window.location so the page
|
||||||
|
// works on both default (HTTP 8080 / WS 8765) and Docker (3000/3001)
|
||||||
|
// port pairings. `?ws=…` query overrides for advanced setups.
|
||||||
|
const wsOverride = new URLSearchParams(window.location.search).get('ws');
|
||||||
state.wsClient = new WebSocketClient({
|
state.wsClient = new WebSocketClient({
|
||||||
url: 'ws://localhost:8000/ws/pose',
|
url: wsOverride || buildSensingWsUrl(),
|
||||||
onMessage: (msg) => handleWebSocketMessage(msg),
|
onMessage: (msg) => handleWebSocketMessage(msg),
|
||||||
onStateChange: (newState, oldState) => handleConnectionStateChange(newState, oldState),
|
onStateChange: (newState, oldState) => handleConnectionStateChange(newState, oldState),
|
||||||
onError: (err) => console.error('[VIZ] WebSocket error:', err)
|
onError: (err) => console.error('[VIZ] WebSocket error:', err)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue