use std::sync::Arc;
use anyhow::Result;
use futures::future::BoxFuture;
use tracing::debug;
use rsclaw_channel::Channel;
use rsclaw_types::OutboundMessage;
use crate::ws::{ConnRegistry, types::EventFrame};
pub struct DesktopChannel {
conns: Arc<ConnRegistry>,
}
impl DesktopChannel {
pub fn new(conns: Arc<ConnRegistry>) -> Self {
Self { conns }
}
}
impl Channel for DesktopChannel {
fn name(&self) -> &str {
"desktop"
}
fn send(&self, msg: OutboundMessage) -> BoxFuture<'_, Result<()>> {
Box::pin(async move {
const KIND_PREFIX: &str = "\u{e000}rsclaw:kind=";
const KIND_PAYLOAD_SEP: char = '\u{e001}';
let (kind, body) = if let Some(rest) = msg.text.strip_prefix(KIND_PREFIX) {
if let Some(sep_idx) = rest.find(KIND_PAYLOAD_SEP) {
let (k, b) = rest.split_at(sep_idx);
(
Some(k.to_owned()),
b[KIND_PAYLOAD_SEP.len_utf8()..].to_owned(),
)
} else {
(None, msg.text.clone())
}
} else {
(None, msg.text.clone())
};
let mut payload = serde_json::json!({
"type": "notification",
"channel": "desktop",
"to": msg.target_id,
"text": body,
});
if let Some(k) = kind.as_ref() {
if let Some(obj) = payload.as_object_mut() {
obj.insert("kind".to_string(), serde_json::Value::String(k.clone()));
}
}
if !msg.images.is_empty() {
if let Some(obj) = payload.as_object_mut() {
obj.insert("images".to_string(), serde_json::json!(msg.images));
}
}
if !msg.files.is_empty() {
if let Some(obj) = payload.as_object_mut() {
obj.insert("files".to_string(), serde_json::json!(msg.files));
}
}
let frame = EventFrame::new("notification", payload, 0);
debug!(
target_id = %msg.target_id,
text_len = msg.text.len(),
image_count = msg.images.len(),
kind = ?kind,
"desktop: broadcasting notification"
);
self.conns.broadcast_all(frame).await;
Ok(())
})
}
fn run(self: Arc<Self>) -> BoxFuture<'static, Result<()>> {
Box::pin(async { Ok(()) })
}
}