use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, Instant};
use crate::feed::DashboardFeed;
use crate::protocol::{DeviceType, RhpServerMsg, Surface};
use crate::session::live;
use crate::store::DeviceStore;
const NUDGE_DEBOUNCE: Duration = Duration::from_secs(2);
pub fn spawn(dashboards: Arc<dyn DashboardFeed>, devices: DeviceStore) {
tokio::spawn(async move {
let mut rx = dashboards.subscribe_changes().await;
let mut last_nudge: HashMap<String, Instant> = HashMap::new();
while let Some(dashboard_id) = rx.recv().await {
let bindings = match dashboards.list_bindings().await {
Ok(b) => b,
Err(_) => continue,
};
for dd in bindings.iter().filter(|d| d.dashboard_id == dashboard_id) {
if !live::is_connected(&dd.device_id).await {
continue;
}
let now = Instant::now();
if let Some(prev) = last_nudge.get(&dd.device_id) {
if now.duration_since(*prev) < NUDGE_DEBOUNCE {
continue;
}
}
let surface = surface_for(&devices, &dd.device_id).await;
let sent = live::send(
&dd.device_id,
RhpServerMsg::Display {
surface,
widget: "dashboard".to_string(),
payload: serde_json::json!({ "action": "repoll" }),
},
)
.await;
if sent {
last_nudge.insert(dd.device_id.clone(), now);
}
}
}
});
}
async fn surface_for(devices: &DeviceStore, device_id: &str) -> Surface {
match devices.get(device_id).await {
Ok(Some(r)) if matches!(r.device_type, DeviceType::Watch) => Surface::Lcd,
_ => Surface::Eink,
}
}