Files
k-frame/crates/adapters/tcp-server/src/broadcaster.rs
Gabriel Kaszewski 26ebfad3a2 add SPA config UI, wire media/rss adapters, event-driven layout push
- React SPA: dashboard, data sources CRUD, widgets CRUD, layout builder,
  presets. TanStack Router + Query, shadcn/ui, Vite proxy to :3000
- wire media + rss adapters into polling loop, remove xtb source type
- media adapter: read username/password from headers, proper subsonic auth
- event handler: subscribe to LayoutChanged, push screen update to clients
- fix clippy warnings across workspace (Default impls, collapsible ifs,
  redundant closures, is_none_or, unused imports)
2026-06-19 00:12:42 +02:00

74 lines
2.0 KiB
Rust

use crate::error::TcpServerError;
use domain::{BroadcastPort, Layout, WidgetId, WidgetState};
use protocol::{ServerMessage, WidgetDescriptor, WireDisplayHint, WireLayoutNode, encode};
use tokio::sync::broadcast;
pub struct TcpBroadcaster {
tx: broadcast::Sender<Vec<u8>>,
}
impl TcpBroadcaster {
pub fn new(capacity: usize) -> Self {
let (tx, _) = broadcast::channel(capacity);
Self { tx }
}
pub fn subscribe(&self) -> broadcast::Receiver<Vec<u8>> {
self.tx.subscribe()
}
fn send_frame(&self, frame: Vec<u8>) -> Result<(), TcpServerError> {
let _ = self.tx.send(frame);
Ok(())
}
}
impl BroadcastPort for TcpBroadcaster {
type Error = TcpServerError;
async fn push_screen_update(
&self,
layout: &Layout,
widgets: &[(WidgetId, WidgetState)],
) -> Result<(), Self::Error> {
let wire_layout: WireLayoutNode = (&layout.root).into();
let wire_widgets: Vec<WidgetDescriptor> = widgets
.iter()
.map(|(id, state)| WidgetDescriptor {
id: *id,
display_hint: WireDisplayHint::IconValue,
state: state.into(),
})
.collect();
let msg = ServerMessage::ScreenUpdate {
layout: wire_layout,
widgets: wire_widgets,
};
let frame = encode(&msg).map_err(TcpServerError::Encode)?;
self.send_frame(frame)
}
async fn push_data_update(
&self,
updates: &[(WidgetId, WidgetState)],
) -> Result<(), Self::Error> {
let wire_widgets: Vec<WidgetDescriptor> = updates
.iter()
.map(|(id, state)| WidgetDescriptor {
id: *id,
display_hint: WireDisplayHint::IconValue,
state: state.into(),
})
.collect();
let msg = ServerMessage::DataUpdate {
widgets: wire_widgets,
};
let frame = encode(&msg).map_err(TcpServerError::Encode)?;
self.send_frame(frame)
}
}