use crate::Channel;
use crate::util::UnwrapPoison;
use crate::{ChannelMessage, SendMessage};
use async_trait::async_trait;
use tokio::sync::mpsc;
pub struct GuiChannel {
gui_rx: std::sync::Mutex<Option<mpsc::UnboundedReceiver<ChannelMessage>>>,
}
impl GuiChannel {
#[must_use]
pub fn new() -> (Self, mpsc::UnboundedSender<ChannelMessage>) {
let (gui_tx, gui_rx) = mpsc::unbounded_channel::<ChannelMessage>();
let channel = Self {
gui_rx: std::sync::Mutex::new(Some(gui_rx)),
};
(channel, gui_tx)
}
}
#[async_trait]
impl Channel for GuiChannel {
async fn send(&self, _message: &SendMessage) -> anyhow::Result<()> {
Ok(())
}
async fn listen(&self, tx: tokio::sync::mpsc::Sender<ChannelMessage>) -> anyhow::Result<()> {
let mut gui_rx = self
.gui_rx
.lock()
.unwrap_poison()
.take()
.expect("GuiChannel::listen() called twice");
while let Some(msg) = gui_rx.recv().await {
if tx.send(msg).await.is_err() {
tracing::info!("GuiChannel: pipeline closed — shutting down listener");
break;
}
}
tracing::info!("GuiChannel: listener stopped");
Ok(())
}
fn name(&self) -> &'static str {
"gui"
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn resolve_recipient(&self, user_name: &str, _reply_target: &str) -> Option<String> {
Some(user_name.to_string())
}
}