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>, } impl TcpBroadcaster { pub fn new(capacity: usize) -> Self { let (tx, _) = broadcast::channel(capacity); Self { tx } } pub fn subscribe(&self) -> broadcast::Receiver> { self.tx.subscribe() } fn send_frame(&self, frame: Vec) -> 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 = 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 = 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) } }