fix(ui): repair sensing UI — OrbitControls import, WebSocket port, toast null container (#760)

Fix three bugs that prevented all live data visualization in the sensing UI:
- Bug 1: Replace CDN OrbitControls with ES module import (Three.js r160 removed examples/js/)
- Bug 2: Correct WebSocket URL from localhost:8000/ws/pose to localhost:3001/ws/sensing
- Bug 3: Guard ToastManager.show() against null container (init() called after show())

Also fix --no-default-features compilation for wifi-densepose-core by adding
conditional alloc imports and replacing std:: references with core:: equivalents.

Co-Authored-By: claude-flow <ruv@ruv.net>
@
This commit is contained in:
zed 2026-05-23 19:09:28 +08:00
parent 1906876541
commit b7233c4dff
6 changed files with 38 additions and 12 deletions

View File

@ -19,6 +19,8 @@ export class ToastManager {
}
show(message, options = {}) {
if (!this.container) this.init();
const {
type = 'info',
duration = 5000,

View File

@ -84,14 +84,26 @@
<div id="stats-container"></div>
</div>
<!-- Three.js and OrbitControls from CDN -->
<script src="https://unpkg.com/three@0.160.0/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.160.0/examples/js/controls/OrbitControls.js"></script>
<!-- Three.js import map (OrbitControls requires ES modules in r160+) -->
<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>
<!-- Stats.js for performance monitoring -->
<script src="https://unpkg.com/stats.js@0.17.0/build/stats.min.js"></script>
<!-- Application modules loaded as ES modules via importmap workaround -->
<script type="module">
// Three.js imports (ES modules required for r160+ OrbitControls)
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
THREE.OrbitControls = OrbitControls;
window.THREE = THREE;
// Import all modules
import { Scene } from './components/scene.js';
import { BodyModel, BodyModelManager } from './components/body-model.js';
@ -177,7 +189,7 @@
// 8. WebSocket client
state.wsClient = new WebSocketClient({
url: 'ws://localhost:8000/ws/pose',
url: 'ws://localhost:3001/ws/sensing',
onMessage: (msg) => handleWebSocketMessage(msg),
onStateChange: (newState, oldState) => handleConnectionStateChange(newState, oldState),
onError: (err) => console.error('[VIZ] WebSocket error:', err)

View File

@ -23,6 +23,9 @@
use thiserror::Error;
#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};
/// A specialized `Result` type for core operations.
pub type CoreResult<T> = Result<T, CoreError>;

View File

@ -18,6 +18,8 @@
//! 3. **Async-Ready**: Async versions available with the `async` feature
//! 4. **Error Handling**: Consistent use of `Result` types with domain errors
#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};
use crate::error::{CoreResult, InferenceError, SignalError, StorageError};
use crate::types::{CsiFrame, FrameId, PoseEstimate, ProcessedSignal, Timestamp};

View File

@ -16,6 +16,13 @@ use ndarray::{Array1, Array2, Array3};
use num_complex::Complex64;
use uuid::Uuid;
#[cfg(not(feature = "std"))]
use alloc::{
format,
string::String,
vec::Vec,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@ -57,8 +64,8 @@ impl Default for FrameId {
}
}
impl std::fmt::Display for FrameId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl core::fmt::Display for FrameId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0)
}
}
@ -82,8 +89,8 @@ impl DeviceId {
}
}
impl std::fmt::Display for DeviceId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl core::fmt::Display for DeviceId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0)
}
}
@ -1003,7 +1010,7 @@ impl PoseEstimate {
a.confidence
.value()
.partial_cmp(&b.confidence.value())
.unwrap_or(std::cmp::Ordering::Equal)
.unwrap_or(core::cmp::Ordering::Equal)
})
}
}

View File

@ -24,7 +24,7 @@ pub fn complex_phase(data: &Array2<Complex64>) -> Array2<f64> {
#[must_use]
pub fn unwrap_phase(phase: &Array1<f64>) -> Array1<f64> {
let mut unwrapped = phase.clone();
let pi = std::f64::consts::PI;
let pi = core::f64::consts::PI;
let two_pi = 2.0 * pi;
for i in 1..unwrapped.len() {
@ -212,7 +212,7 @@ mod tests {
fn test_deg_rad_conversion() {
let degrees = 180.0;
let radians = deg_to_rad(degrees);
assert!((radians - std::f64::consts::PI).abs() < 1e-10);
assert!((radians - core::f64::consts::PI).abs() < 1e-10);
let back = rad_to_deg(radians);
assert!((back - degrees).abs() < 1e-10);
@ -226,7 +226,7 @@ mod tests {
#[test]
fn test_unwrap_phase() {
let pi = std::f64::consts::PI;
let pi = core::f64::consts::PI;
// Simulate a phase wrap
let phase = array![0.0, pi / 2.0, pi, -pi + 0.1, -pi / 2.0];
let unwrapped = unwrap_phase(&phase);