use futures_channel::{mpsc, oneshot};
use futures_util::future;
use wasm_bindgen::{JsCast, JsValue};
pub struct Interface {
pub(crate) port: crate::port::Port,
pub(crate) listener: gloo_events::EventListener,
pub(crate) messages_rx: mpsc::UnboundedReceiver<js_sys::Array>,
}
impl Interface {
pub async fn new(port: impl Into<crate::port::Port>) -> Self {
let port = port.into();
let (dispatcher_tx, dispatcher_rx) = mpsc::unbounded();
let (ready_tx, ready_rx) = oneshot::channel();
let mut ready_tx = Option::from(ready_tx);
let listener =
gloo_events::EventListener::new(port.event_target(), "message", move |event| {
let message = event.unchecked_ref::<web_sys::MessageEvent>().data();
match message.dyn_into::<js_sys::Array>() {
Ok(array) => {
let _ = dispatcher_tx.unbounded_send(array);
}
Err(_) => {
if let Some(ready_tx) = ready_tx.take() {
let _ = ready_tx.send(());
}
}
}
});
port.start();
let port_cloned = port.clone();
let poll = async move {
loop {
port_cloned
.post_message(&JsValue::NULL, &JsValue::UNDEFINED)
.unwrap();
gloo_timers::future::TimeoutFuture::new(10).await;
}
};
pin_utils::pin_mut!(poll);
future::select(ready_rx, poll).await;
port.post_message(&JsValue::NULL, &JsValue::UNDEFINED)
.unwrap();
Self {
messages_rx: dispatcher_rx,
listener,
port,
}
}
}