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 = {}) { show(message, options = {}) {
if (!this.container) this.init();
const { const {
type = 'info', type = 'info',
duration = 5000, duration = 5000,

View File

@ -84,14 +84,26 @@
<div id="stats-container"></div> <div id="stats-container"></div>
</div> </div>
<!-- Three.js and OrbitControls from CDN --> <!-- Three.js import map (OrbitControls requires ES modules in r160+) -->
<script src="https://unpkg.com/three@0.160.0/build/three.min.js"></script> <script type="importmap">
<script src="https://unpkg.com/three@0.160.0/examples/js/controls/OrbitControls.js"></script> {
"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 --> <!-- 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>
<!-- Application modules loaded as ES modules via importmap workaround --> <!-- Application modules loaded as ES modules via importmap workaround -->
<script type="module"> <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 all modules
import { Scene } from './components/scene.js'; import { Scene } from './components/scene.js';
import { BodyModel, BodyModelManager } from './components/body-model.js'; import { BodyModel, BodyModelManager } from './components/body-model.js';
@ -177,7 +189,7 @@
// 8. WebSocket client // 8. WebSocket client
state.wsClient = new WebSocketClient({ state.wsClient = new WebSocketClient({
url: 'ws://localhost:8000/ws/pose', url: 'ws://localhost:3001/ws/sensing',
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)

View File

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

View File

@ -18,6 +18,8 @@
//! 3. **Async-Ready**: Async versions available with the `async` feature //! 3. **Async-Ready**: Async versions available with the `async` feature
//! 4. **Error Handling**: Consistent use of `Result` types with domain errors //! 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::error::{CoreResult, InferenceError, SignalError, StorageError};
use crate::types::{CsiFrame, FrameId, PoseEstimate, ProcessedSignal, Timestamp}; use crate::types::{CsiFrame, FrameId, PoseEstimate, ProcessedSignal, Timestamp};

View File

@ -16,6 +16,13 @@ use ndarray::{Array1, Array2, Array3};
use num_complex::Complex64; use num_complex::Complex64;
use uuid::Uuid; use uuid::Uuid;
#[cfg(not(feature = "std"))]
use alloc::{
format,
string::String,
vec::Vec,
};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -57,8 +64,8 @@ impl Default for FrameId {
} }
} }
impl std::fmt::Display for FrameId { impl core::fmt::Display for FrameId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0) write!(f, "{}", self.0)
} }
} }
@ -82,8 +89,8 @@ impl DeviceId {
} }
} }
impl std::fmt::Display for DeviceId { impl core::fmt::Display for DeviceId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0) write!(f, "{}", self.0)
} }
} }
@ -1003,7 +1010,7 @@ impl PoseEstimate {
a.confidence a.confidence
.value() .value()
.partial_cmp(&b.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] #[must_use]
pub fn unwrap_phase(phase: &Array1<f64>) -> Array1<f64> { pub fn unwrap_phase(phase: &Array1<f64>) -> Array1<f64> {
let mut unwrapped = phase.clone(); let mut unwrapped = phase.clone();
let pi = std::f64::consts::PI; let pi = core::f64::consts::PI;
let two_pi = 2.0 * pi; let two_pi = 2.0 * pi;
for i in 1..unwrapped.len() { for i in 1..unwrapped.len() {
@ -212,7 +212,7 @@ mod tests {
fn test_deg_rad_conversion() { fn test_deg_rad_conversion() {
let degrees = 180.0; let degrees = 180.0;
let radians = deg_to_rad(degrees); 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); let back = rad_to_deg(radians);
assert!((back - degrees).abs() < 1e-10); assert!((back - degrees).abs() < 1e-10);
@ -226,7 +226,7 @@ mod tests {
#[test] #[test]
fn test_unwrap_phase() { fn test_unwrap_phase() {
let pi = std::f64::consts::PI; let pi = core::f64::consts::PI;
// Simulate a phase wrap // Simulate a phase wrap
let phase = array![0.0, pi / 2.0, pi, -pi + 0.1, -pi / 2.0]; let phase = array![0.0, pi / 2.0, pi, -pi + 0.1, -pi / 2.0];
let unwrapped = unwrap_phase(&phase); let unwrapped = unwrap_phase(&phase);