use dioxus_core::use_hook;
use dioxus_signals::{ReadableExt, Signal, WritableExt};
use futures_channel::oneshot::{Canceled, Receiver, Sender};
use futures_util::{future::Shared, FutureExt};
pub fn use_waker<T: Clone + 'static>() -> UseWaker<T> {
let (task_tx, task_rx) = use_hook(|| {
let (tx, rx) = futures_channel::oneshot::channel::<T>();
let shared = rx.shared();
(Signal::new(tx), Signal::new(shared))
});
UseWaker { task_tx, task_rx }
}
#[derive(Debug)]
pub struct UseWaker<T: 'static> {
task_tx: Signal<Sender<T>>,
task_rx: Signal<Shared<Receiver<T>>>,
}
impl<T: Clone + 'static> UseWaker<T> {
pub fn wake(&mut self, value: T) {
let (tx, rx) = futures_channel::oneshot::channel::<T>();
let shared = rx.shared();
let tx = self.task_tx.replace(tx);
let _rx = self.task_rx.replace(shared);
let _ = tx.send(value);
}
pub async fn wait(&self) -> Result<T, Canceled> {
self.task_rx.cloned().await
}
}
impl<T: Clone + 'static> std::future::Future for UseWaker<T> {
type Output = Result<T, Canceled>;
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
self.task_rx.peek().clone().poll_unpin(cx)
}
}
impl<T> Copy for UseWaker<T> {}
impl<T> Clone for UseWaker<T> {
fn clone(&self) -> Self {
*self
}
}